总结四

本文详细解析Unity中资源加载的多种方式,包括Resources.Load、AssetBundle.Load及不同加载方式的优劣对比。深入探讨了内存管理策略,如AssetsBundle加载、卸载机制,以及如何有效减少内存占用,确保游戏流畅运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;

namespace Assets.UnityTest
{
    /// <summary>
    /// 插件里的方法如何在lua里调用
    /// 小地图问题
    /// probuf协议
    /// lua、C#交互性能问题优化
    /// unity动态加载和内存管理
    /// unity俩种动态加载方式:(1)Resouces.Load();(2)Assetsboundle.Load()
    /// 
    /// AssetsBoundle运行时加载:
    /// 来自文件加载用CreateFromFile(这里只能用于standalone程序)这是最快的加载方法
    /// 来自缓存的加载用CrateFromMemory(byte[])byte可以来自文件读取的缓存,www的下载或其他可能的方式
    /// www的assetsboundle是内部数据读取完成后自己创建了一个assetsboundle而已
    /// Create等于把硬盘或者网络的文件读取到一个内存区域,这时候只是个AssetsBoundle内存镜像数据块,还没有Assets的感念
    /// Assets加载:
    /// AssetsBoundle.Load()(同Rescource.Load())这时会从AssetsBoundle内存镜像里读取并创建一个Assets,创建Assets对象,同时分配相应的内存进行存放(反序列化)
    /// 
    /// AssetsBoundle的释放:
    /// AssetsBoundle.UnLoad(false);只释放镜像内存,不包含Load创建出来的Assets内存对象
    /// AssetsBoundle.UnLoad(true);释放镜像内存,并销毁所有Load创建出来的Assets内存对象
    /// Destory()一个实例的时候,只会释放掉克隆,不会释放引用对象和克隆对象的数据源对象,Destory()并不知道是否还有别的Object在引用那些对象
    /// 
    /// 当游戏中没有任何场景引用这些Assets以后,这些Assets就成了没有引用的数据块了。就用Rescpource.UnLoadUnUseAssets来释放Destory不能释放的任务。
    /// AssetBundle.Unload(false)也不行,AssetBundle.Unload(true)可以但不安全,除非你很清楚没有任何对象在用这些Assets了。
    /// 
    /// 关于内存管理:
    /// (1)先创建一个AssetsBoundle,无论是文件还是www还是memory
    /// (2)用AssetsBoundle.Load()加载对象
    /// (3)加载完成后立即AsssetsBoundle.Unload(false)释放掉Assets的镜像内存,但不销毁加载的assets对象
    /// 释放时:
    /// (1)如果有Instence对象,用Destory进行销毁
    /// (2)在合适的地方进行Rescouse.UnLoadUnUseAssets()释放镜像内存
    /// (3)如果需要立即释放内存需要加上CG.Collect(),否则内存不会立即释放,有时候可能导致内存没有立即释放而引发异常
    ///  这样可以保证内存始终被及时释放,占用量最少。也不需要对每个加载的对象进行引用。
    ///  系统在切换新的场景时,所有的内存对象都会被自动销毁,包括AssetsBound.Load()和Instence对象。但不包括AssetsBoundle文件自身的镜像内存,必须用UnLoad进行释放
    ///  
    /// 
    ///  
    /// Unity的内存种类:程序代码、托管堆以及本机堆
    /// 
    /// 
    ///  
    /// </summary>
    /// 

    //AssetsBundle只能加载ab资源,当前设备允许访问的路径都可以
    class AssetsBundleTest:MonoBehaviour
    {
        GameObject obj;
        AssetBundleManifest manifestBundle;
        IEnumerator<AssetBundle> LoadAB()
        {
            //来自文件的加载,先加载ab资源到镜像内存
            AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/../../../DarklyRes/Android/thr/models/npcs/npc110.ly");
            yield return ab;

            manifestBundle = ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            string[] manifest = manifestBundle.GetAllDependencies("npc110");

            for (int i = 0; i < manifest.Length; i++)
            {
                AssetBundle.LoadFromFile(manifest[i].ToString());
            }
            //从镜像内存中加载到内存,并创建assets对象
            obj = ab.LoadAsset<GameObject>("npc110");
            //释放镜像内存
            ab.Unload(false);
            //创建实例
            Instantiate(obj);
        }

        private void OnDestroy()
        {
            if (obj == null) return;
            //释放克隆
            DestroyImmediate(obj,true);
            //释放掉所有的引用
            Resources.UnloadUnusedAssets();
            //立即释放内存
            GC.Collect();
        }

        private void Start()
        {
            //StartCoroutine(LoadAB());
        }

    }
    /// <summary>
    /// 同步异步:
    /// 同步:指定协程步调,协助,相互配合;按照先后顺序执行,在没有得到返回结果之前会一直等待,不会继续往下执行
    /// 异步:在同一个功能调用时,不管用没有结果都会继续执行,异步加载至少有一帧的延迟
    /// 同步的优点:管理方便,资源准备好可以及时返回,缺点:没有异步快
    /// 异步的优点:速度快,和主线程无关;调用比较麻烦,最好的方法是使用回调
    /// 
    ///
    /// </summary>
    interface LoadInterface<T> where T:UnityEngine.Object
    {
        void LoadResourcesObject(T t,string path,bool IsAsync);
        void UnLoadResourcesObject(T t);
    }

    class LoadResourcesBase<T>:LoadInterface<T> where T:UnityEngine.Object
    {
        
        virtual public void LoadResourcesObject(T t, string path, bool IsAsync)
        {
            throw new NotImplementedException();
        }
        virtual public void UnLoadResourcesObject(T t)
        {
            throw new NotImplementedException();
        }
    }

    class LoadResources<T> : LoadResourcesBase<T> where T : UnityEngine.Object
    {
        MonoBehaviour MB;
        public override void LoadResourcesObject(T t, string path, bool IsAsync)
        {
            base.LoadResourcesObject(t, path, IsAsync);
            //Resource方式加载
            ResourceLoad(t, path, IsAsync);

        }

        public override void UnLoadResourcesObject(T t)
        {
            base.UnLoadResourcesObject(t);
        }
        /// <summary>
        /// resource加载;只能加载resources目录下的资源
        /// </summary>
        /// <param name="t"></param>
        /// <param name="path"></param>
        /// <param name="IsAsync"></param>
        void ResourceLoad(T t,string path,bool IsAsync)
        {
            if (IsAsync == false)
            {
                T obj = Resources.Load(path) as T;
                t = obj;
                /*
                 * 
                 * 
                */
                Resources.UnloadAsset(t);
            }
            else
            {
                T obj = Resources.LoadAsync(path) as T;
                t = obj;
                /*
                 * 
                 * 
                */
                Resources.UnloadAsset(t);
            }
        }
        /// <summary>
        /// AssetsDataBase.Load加载  只能加载Assets下的资源,但是用于Editor
        /// </summary>
        /// <param name="t"></param>
        /// <param name="path"></param>
        /// <param name="IsAsync"></param>
        void AssetsDataBaseLoad(T t,string path,bool IsAsync)
        {
            if (IsAsync == false)
            {
                T obj = AssetDatabase.LoadAssetAtPath<T>(path);

                t = obj;

                /*
                 * 
                */
                Resources.UnloadAsset(t);
            }else
                Console.WriteLine("AssetsDatabase没有异步加载");
        }
        /// <summary>
        /// www加载  可以加载任意处的资源,包括服务器
        /// </summary>
        /// <param name="t"></param>
        /// <param name="path"></param>
        /// <param name="IsAsync"></param>
        void WWWResLoad(T t,string url,bool IsAsync)
        {
            if (IsAsync == false) { Console.WriteLine("www没有同步加载"); }
            else
            {
                MB.StartCoroutine(AsyncLoad(t,url));
            }
        }

        IEnumerator<T> AsyncLoad(T t,string url)
        {
            T www = new WWW(url) as T;
            yield return www;
            /*
            ...
            */
            Resources.UnloadAsset(t);
            yield return null;
        }
        /// <summary>
        /// unitywebrequstLoad加载   www的升级版
        /// </summary>
        /// <param name="t"></param>
        /// <param name="url"></param>
        /// <param name="IsAsync"></param>
        void UnityWebRequstLoad(T t,string url,bool IsAsync)
        {
            if (IsAsync == true)
            {
                MB.StartCoroutine(UnityRequstAsync(t, url));
            }else
                Console.WriteLine("UnityWebRequstLoad没有同步");
        }

        IEnumerator<T> UnityRequstAsync(T t,string url)
        {
            T obj = new UnityWebRequest(url) as T;
            t = obj;
            /*
             ...
             */
            Resources.UnloadAsset(t);
            yield return null;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值