Unity三种加载方式详解

    xiaoxiao2023-11-27  191

    Unity三种加载方式详解

    前言有三种资源加载方式:资源的加载与卸载一般的加载流程:一般的释放流程:一个容易出错的例子:

    前言

    感谢转载自博客主周小菲的博客,原贴地址:http://www.cnblogs.com/zhoujiangyue/articles/7066070.html

    有三种资源加载方式:

    1.静态引用。具体操作:创建public变量,把文件挂到物体上,在Inspector里把相应资源给public变量,用的时候instantiate或者直接用。

    2.Resources.Load 加载Resources文件夹下的资源,加载后instantiate.

    3.AssetBundle.Load 加载打包后的资源。

    前两种资源加载方式,对于引用对象是在instantiate时加载的,而不是在加载时直接加载的,所以有时会造成第一次加载时客户端卡顿。

    第三种资源加载方式,在加载时会加载所有引用资源,instantiate时只是生成克隆。

    资源的加载与卸载

    说到Unity资源的卸载,就需要先了解要卸载什么。其实就是要卸载资源所占用的内存,使资源占用的内存释放。

    资源所占用内存的形式一般是三种:

    1 . assetbundle镜像文件: assetbundle文件内存镜像占用的内存,在加载assetbundle文件完成后,会在内存中形成assetbundle文件的内存镜像,同一个assetbundle文件不能有两个内存镜像,所以同一个assetbundle文件在没有Unload之前不能再次加载。

    2 . 加载出来的资源文件:从assetbundle文件中加载出来的资源所占的内存(AssetBundle.Load多次Load只会有一份资源内存占用)。(指GameObject,Texture,Sprite,Shader,Material)如果从assetbundle里加载的资源是引用类型的,就不需要实例化就可以直接使用,并且如果有多个地方使用同一个引用资源时,引用资源不需要实例化,比如:Texture,Sprite,Shader,Material就是引用类型的。如果assetbundle里加载的资源不是引用句类型,不能直接使用,需要实例化后使用,如:GameObject,需要Instantiate实例化后使用。如果需要多个GameObject,需要多次实例化。(也就是游戏对象需要实例化出来,而资源图片材质等则可以直接使用,这种形式说的为)

    3 . 实例化出来的游戏对象:Instantiate实例化的资源所占用的内存。(一般是指GameObject)

    AssetBundle.UnLoad(false);卸载镜像文件,上述的第一种。

    AssetBundle.UnLoad(true);卸载上述1和2的内存占用(所有此AssetBundle已经加载的资源)。

    如果想要只卸载某个已经加载的资源,用Resources.UnLoadAsset(obj)(只能用这个卸载引用资源,不能卸载游戏物体);Resources.UnloadUnusedAsset()卸载没有被引用的所有的资源。

    Destroy主要用来销毁3的内存占用,即销毁克隆对象,也可用于销毁静态物体,不会自动释放该对象的所有引用。Destroy不能用来销毁从文件加载的资源(会删除相应的资源文件,报错Destroying assets is not permitted to avoid data loss.) 加载新场景时会自动销毁2,3的内存占用,但是1的内存占用不会销毁,1只能通过AssetBundle.Unload去释放。

    一般的加载流程:

    1.创建assetbundle(WWW www = new WWW(url)) 2.用AssetBundle.Load加载需要的资源 3.判断资源的种类,根据种类去选择下一步操作(可把资源分为共享资源和非共享资源,或者根据使用频率选择是否保存已经加载过的资源等) 4.确保加载完成后,调用AssetBundle.Unload(false)去卸载1创建出的镜像文件。

    一般的释放流程:

    1.如果克隆了对象,用Destroy去销毁。 2.在合适的地方调用Resources.UnloadUnusedAsset(),释放已经没有引用的资源(就是没有地方在用的资源,引用计数为0) 3.如果是想卸载单独的一个用Load加载的资源,用Resources.UnloadAsset(obj)释放(只能用这个卸载引用资源) 4.如果想要立即释放调用GC.Collect()。

    一个容易出错的例子:

    UnityEngine.Object obj = Resources.Load("MyPrefab"); GameObject instance = Instantiate(obj) as GameObject; Destroy(instance); Resources.UnloadUnusedAssets(); 这时,内存并没有释放掉,因为MyPrefab还被obj这个变量所这用。 obj = null; Resources.UnloadUnusedAssets(); 这样才能真正释放 Resources.UnloadUnusedAssets()不但要没有实际物体引用,也要没有被生命周期内的变量所引用,才可以释放。
    最新回复(0)