Unity中,使用資源加載系統(tǒng)加載資源

說(shuō)明

該資源系統(tǒng)提供如下方法:
通過(guò)名稱異步加載預(yù)制體、場(chǎng)景、音頻資源、精靈圖等UnityObject。

當(dāng)前還是將資源全部放在本地,通過(guò)該系統(tǒng)(而非其他方式,如直接Resources.Load)加載資源是為了方便后續(xù)改為從遠(yuǎn)端獲取資源。

使用

  1. 根據(jù)快速開(kāi)始 | YooAsset里的描述,安裝YooAsset。

  2. 根據(jù)全局配置 | YooAsset里的描述,在Resources下創(chuàng)建YooAssetSettings。

  3. Assets下創(chuàng)建目錄AssetsPackage,其下創(chuàng)建幾個(gè)子目錄AudioClips、Prefabs、Scenes、Sprites、……,將各類資源放到相應(yīng)子目錄下。

  4. YooAsset->AssetBundle Collector:創(chuàng)建Package,Enable Addressable打勾->Groups(上述每個(gè)子目錄對(duì)應(yīng)一個(gè)Group:子目錄拖到Group的Collector處)

  5. YooAsset->AssetBundle Builder:BuildVersion設(shè)置為v1.0.0,CopyBuildinFileOption設(shè)置為Clear And Copy All(自動(dòng)創(chuàng)建StreamingAssets\yoo,將所有資源包復(fù)制到該目錄下)

  6. 如下是一個(gè)使用ResourceSys的例子(具體代碼見(jiàn)后文):
    在Launch場(chǎng)景(唯一需要Build的場(chǎng)景)中有一Launcher,在其中初始化ResourceSys。完成后載入并進(jìn)入目標(biāo)場(chǎng)景,進(jìn)入后游戲開(kāi)始:載入預(yù)制體并創(chuàng)建副本、載入并播放音效、載入并將精靈圖顯示在Image上。

  7. 說(shuō)明:在編輯器模式下,載入音效會(huì)報(bào)錯(cuò),無(wú)法播放。但是打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加載

說(shuō)明

  1. 先將所有資源放到Resources下,通過(guò)Resources加載:需傳入相對(duì)Resources的路徑,而非資源名稱。
  2. 需要把場(chǎng)景添加到BuildSettings中。
  3. 所有資源都通過(guò)FanResourceSys加載,而不是直接調(diào)用Resources.Load。
  4. 方便后續(xù)將資源放在遠(yuǎn)端,修改加載方式。

使用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
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容