首页 > Godot频道 > 【Godot学习笔记】 > Godot学习笔记之资源加载卸载(六)
2025
03-18

Godot学习笔记之资源加载卸载(六)

Godot并没有提供异步加载接口,而是通过ResourceLoader.LoadThreadedRequest(path)启动一个线程来加载,需要使用者在update中进行轮训查看加载结果。

先来看看这段代码,代码中并没有处理异常,我们先不管它。流程上是OK的,可以进行一个异步加载的调用,并且有回调

因为不能卡死主线程就需要Task.Run在开一个线程进行资源加载结果的轮训,当加载完毕后还需要在回到主线程将结果抛出事件,还有一种方法是用Task.Delay在循环中异步等待。这两种方法我感觉都不是很好,因为需要在主线程和子线程中间切换,我觉得更安全的做法应该是在主线程update中轮训。

为什么godot不设计一个带回调的异步加载接口呢? 带着疑问只能看它的源码了~打开resource_loader.cpp文件在Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start方法中

注意看p_thread_mode,LOAD_THREAD_FROM_CURRENT表示主线程加载,也是当前线程加载会同时执行_run_load_task方法,如果是子线程加载它的值是LOAD_THREAD_SPAWN_SINGLE,代码会开始一个子线程来执行ResourceLoader::_run_load_task 加载方法。

Godot学习笔记之资源加载卸载(六) - 雨松MOMO程序研究院 - 1

所以同步加载方法ResourceLoader.Load<Texture2D>就可以在当前帧拿到加载结果,如果是线程加载就得找地方进行轮训结果了,godot引擎并没有帮我们做这个,它并没有提供异步加载的方法。

再来看看资源的卸载,来看看下面这段代码,加载贴图赋值给textureRect对象。点击按钮后删除节点,此时c#托管堆对象并没有释放,必须进行GC后,这样C++那边才能知道对象已经被卸载。

godot资源卸载使用了引用计数的方法,当引用计数为0会自动卸载内存,不需要开发者手动执行什么。

c#托管对象释放掉后会回调c++中godotsharp_internal_refcounted_disposed方法,godot中所有对象都是继承refCounted,它内部有一套引用计数的管理器,rc->unreference()为true则表示引用计数为0就可以真正free内存了。

runtime_interop.cpp

Godot学习笔记之资源加载卸载(六) - 雨松MOMO程序研究院 - 2

比如加载出来的Texture2D对象,可能会被多个UI引用,这样就需要所有UI都销毁了它的引用数量才能为0,才能被真正销毁掉。每次引用的时候计数器会+1, 每次销毁的时候计数器-1,这样就可以自动管理释放内存了, 这种引用计数的方法是目前解决不了环形引用的问题。

 

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

留下一个回复

你的email不会被公开。