美文网首页unity W...
Unity中,使用资源加载系统加载资源

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

作者: 全新的饭 | 来源:发表于2024-03-31 16:52 被阅读0次

说明

该资源系统提供如下方法:
通过名称异步加载预制体、场景、音频资源、精灵图等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
}

相关文章

  • Unity AssetBundle 资源无法卸载,导致内存泄漏

    我们在使用Unity 使用AssetBundle加载资源时,在资源加载完成后不能调用 AssetBundle.un...

  • Unity3D WWW用file协议下载失败问题

    Unity3D中加载本地或远程资源会用到WWW类,最使用Unity3D的WWW类加载本地磁盘资源时发现总是加载失败...

  • Unity Addressable Asset System 文

    简介 Unity可寻址资源系统 可寻址资源系统提供了一种简单的方法通过“地址”加载资源。简化资源包的创建和部署的管...

  • Unity 加载资源

    在Resources文件夹里面放入资源。加载如: 扩展方法-扩展系统组件ref 、out、params参数区别 r...

  • Unity资源加载

    资源加载 一、public 面板拖拽。大项目和多人项目基本都用不到。 二、Resources.load 商用不...

  • Unity3d常用两种加载资源方案:Resources.Load

    初步整理并且学习unity3d资源加载方法,预计用时两天完成入门学习Unity3d常用两种加载资源方案:Resou...

  • unity内存优化

    unity的内存优化主要集中在一下三块: www加载资源管理 美术资源管理 UI功能管理 www加载资源管理 原文...

  • 运行环境

    一、加载资源的形式 输入URL(或跳转页面)加载HTML 加载HTML中的静态资源 二、加载资源的过程 DNS解析...

  • webkit资源加载机制

    资源加载器 1. 特定资源加载器,加载特定资源,比如image对应ImageLoader 2. 缓存机制的资源加载...

  • 使用 preconnect 提前与服务端建立连接

    preload 使用preload加载最重要的资源,以高优先级加载资源 允许浏览器设定资源加载的优先级 赋予浏览器...

网友评论

    本文标题:Unity中,使用资源加载系统加载资源

    本文链接:https://www.haomeiwen.com/subject/cnhbtjtx.html