Unity中,使用资源加载系统加载资源

说明

该资源系统提供如下方法:
通过名称异步加载预制体、场景、音频资源、精灵图等UnityObject。

当前还是将资源全部放在本地,通过该系统(而非其他方式,如直接Resources.Load)加载资源是为了方便后续改为从远端获取资源。

使用

  1. 根据快速开始 | YooAsset里的描述,安装YooAsset。

  2. 根据全局配置 | YooAsset里的描述,在Resources下创建YooAssetSettings。

  3. Assets下创建目录AssetsPackage,其下创建几个子目录AudioClips、Prefabs、Scenes、Sprites、……,将各类资源放到相应子目录下。

  4. YooAsset->AssetBundle Collector:创建Package,Enable Addressable打勾->Groups(上述每个子目录对应一个Group:子目录拖到Group的Collector处)

  5. YooAsset->AssetBundle Builder:BuildVersion设置为v1.0.0,CopyBuildinFileOption设置为Clear And Copy All(自动创建StreamingAssets\yoo,将所有资源包复制到该目录下)

  6. 如下是一个使用ResourceSys的例子(具体代码见后文):
    在Launch场景(唯一需要Build的场景)中有一Launcher,在其中初始化ResourceSys。完成后载入并进入目标场景,进入后游戏开始:载入预制体并创建副本、载入并播放音效、载入并将精灵图显示在Image上。

  7. 说明:在编辑器模式下,载入音效会报错,无法播放。但是打web包后可正常播放。因此在编辑器模式下初始化YooAsset使用编辑器模拟模式。

具体代码

FanResourceSys.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;

public class FanResourceSys
{
    public static FanResourceSys Instance { get; private set; }
    public static bool TryInitialize(Action callback = null)
    {
        var ret = false;
        if (Instance == null)
        {
            Instance = new FanResourceSys(callback);
            ret = true;
        }
        return ret;
    }
    private const string PackageName = "DefaultPackage";
    private ResourcePackage _package;
    private FanResourceSys(Action initializeCallback)
    {
        YooAssets.Initialize();
        _package = YooAssets.CreatePackage(PackageName);
        YooAssets.SetDefaultPackage(_package);
        MonoSys.Instance.StartCoroutine(InitializeYooAsset(initializeCallback));

        IEnumerator InitializeYooAsset(Action initializeCallback)
        {
#if UNITY_EDITOR
            var initParameters = new EditorSimulateModeParameters();
            var simulateManifestFilePath = EditorSimulateModeHelper.SimulateBuild(EDefaultBuildPipeline.BuiltinBuildPipeline, PackageName);
            initParameters.SimulateManifestFilePath = simulateManifestFilePath;
            yield return _package.InitializeAsync(initParameters);
            initializeCallback?.Invoke();
#elif UNITY_WEBGL
            // string defaultHostServer = "http://localhost:8000/CDN/Test/v1.0.0";
            // string fallbackHostServer = "http://localhost:8000/CDN/Test/v1.0.0";
            string defaultHostServer = string.Empty;
            string fallbackHostServer = string.Empty;
            var initParameters = new WebPlayModeParameters();
            initParameters.BuildinQueryServices = new GameQueryServices();
            initParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
            var initOperation = _package.InitializeAsync(initParameters);
            yield return initOperation;

            if (initOperation.Status == EOperationStatus.Succeed)
            {
                Debug.Log("资源包初始化成功!");
                initializeCallback?.Invoke();
            }
            else
            {
                Debug.LogError($"资源包初始化失败:{initOperation.Error}");
            }
#else
            var initParameters = new OfflinePlayModeParameters();
            yield return _package.InitializeAsync(initParameters);
            initializeCallback?.Invoke();
#endif
        }
    }
    public void Destroy()
    {
        Instance = null;
    }

    #region 加载
    public void LoadPrefab(string name, Action<GameObject> callback)
    {
        LoadUnityObj(name, callback);
    }
    public void LoadScene(string name, Action callback)
    {
        var handle = _package.LoadSceneAsync(name, UnityEngine.SceneManagement.LoadSceneMode.Single, false);
        handle.Completed += h =>
        {
            callback?.Invoke();
        };
    }
    public void LoadAudioClip(string name, Action<AudioClip> callback)
    {
        LoadUnityObj(name, callback);
    }
    public void LoadSprite(string name, Action<Sprite> callback)
    {
        LoadUnityObj(name, callback);
    }
    public void LoadUnityObj<T>(string name, Action<T> callback) where T : UnityEngine.Object
    {
        var handle = _package.LoadAssetAsync<T>(name);
        handle.Completed += h =>
        {
            callback?.Invoke(h.AssetObject as T);
        };
    }
    #endregion

    #region 卸载
    public void UnloadUnusedAssets()
    {
        YooAssets.GetPackage(PackageName).UnloadUnusedAssets();
    }
    public void UnloadAllAssets()
    {
        YooAssets.GetPackage(PackageName).ForceUnloadAllAssets();
    }
    #endregion

    private class GameQueryServices : IBuildinQueryServices
    {
        public bool Query(string packageName, string fileName, string fileCRC)
        {
            return true;
        }
    }
    private class RemoteServices : IRemoteServices
    {
        private readonly string DefaultHostServer;
        private readonly string FallbackHostServer;
        public RemoteServices(string defaultHostServer, string fallbackHostServer)
        {
            DefaultHostServer = defaultHostServer;
            FallbackHostServer = fallbackHostServer;
        }
        public string GetRemoteFallbackURL(string fileName)
        {
            return FallbackHostServer;
        }

        public string GetRemoteMainURL(string fileName)
        {
            return DefaultHostServer;
        }
    }
}

Launcher.cs

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class Launcher : MonoBehaviour
{
    [SerializeField]
    private string _firstSceneName = "1";

    private void Start()
    {
        Init();
    }

    private void Update()
    {
        MyUpdate();
    }

    private void OnDestroy()
    {
        Destroy();
    }

    private void Init()
    {
        FanResourceSys.TryInitialize(() => FanResourceSys.Instance.LoadScene(_firstSceneName, GameStart));

        void GameStart()
        {
            FanResourceSys.Instance.LoadPrefab("Cube", prefab =>
            {
                var go = Instantiate(prefab);
                var au = go.AddComponent<AudioSource>();
                au.loop = true;
                FanResourceSys.Instance.LoadAudioClip("countdown", clip =>
                {
                    au.clip = clip;
                    au.Play();
                });
            });


            var canvas = new GameObject().AddComponent<Canvas>();
            canvas.renderMode = RenderMode.ScreenSpaceOverlay;
            var imgGo = new GameObject();
            imgGo.transform.SetParent(canvas.transform);
            imgGo.transform.localPosition = Vector3.zero;
            var img = imgGo.AddComponent<UnityEngine.UI.Image>();
            FanResourceSys.Instance.LoadSprite("Icon_Tx_04", sprite =>
            {
                img.sprite = sprite;
            });

        }
    }

    private void MyUpdate()
    {

    }

    private void Destroy()
    {

    }
}

先直接使用Resources加载

说明

  1. 先将所有资源放到Resources下,通过Resources加载:需传入相对Resources的路径,而非资源名称。
  2. 需要把场景添加到BuildSettings中。
  3. 所有资源都通过FanResourceSys加载,而不是直接调用Resources.Load。
  4. 方便后续将资源放在远端,修改加载方式。

使用Resources.Load的代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
using UnityEngine;
using UnityEngine.SceneManagement;
using YooAsset;

public class FanResourceSys
{
    public static FanResourceSys Instance { get; private set; }
    public static bool TryInitialize(Action callback = null)
    {
        var ret = false;
        if (Instance == null)
        {
            Instance = new FanResourceSys();
            callback?.Invoke();
            ret = true;
        }
        return ret;
    }
    private FanResourceSys()
    {

    }

    public void Destroy()
    {
        Instance = null;
    }

    #region 加载
    public void LoadUnityObj<T>(string path, Action<T> callback) where T : UnityEngine.Object
    {
        var request = Resources.LoadAsync<T>(path);
        request.completed += oper =>
        {
            var asset = request.asset as T;
            if (asset != null)
            {
                callback.Invoke(asset);
            }
            else
            {
                Debug.LogError(path + " 读取失败!");
            }
        };
    }
    public void LoadPrefab(string path, Action<GameObject> callback)
    {
        LoadUnityObj(path, callback);
    }
    public void LoadAudioClip(string path, Action<AudioClip> callback)
    {
        LoadUnityObj(path, callback);
    }
    public void LoadSprite(string path, Action<Sprite> callback)
    {
        LoadUnityObj(path, callback);
    }
    public void LoadScene(string name, Action callback)
    {
        var oper = SceneManager.LoadSceneAsync(name);
        oper.completed += oper =>
        {
            callback?.Invoke();
        };
    }
    #endregion
    #region 卸载
    public void UnloadUnusedAssets()
    {
        Resources.UnloadUnusedAssets();
    }
    #endregion
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容