说明
该资源系统提供如下方法:
通过名称异步加载预制体、场景、音频资源、精灵图等UnityObject。
当前还是将资源全部放在本地,通过该系统(而非其他方式,如直接Resources.Load)加载资源是为了方便后续改为从远端获取资源。
使用
根据快速开始 | YooAsset里的描述,安装YooAsset。
根据全局配置 | YooAsset里的描述,在Resources下创建YooAssetSettings。
Assets下创建目录AssetsPackage,其下创建几个子目录AudioClips、Prefabs、Scenes、Sprites、……,将各类资源放到相应子目录下。
YooAsset->AssetBundle Collector:创建Package,Enable Addressable打勾->Groups(上述每个子目录对应一个Group:子目录拖到Group的Collector处)
YooAsset->AssetBundle Builder:BuildVersion设置为v1.0.0,CopyBuildinFileOption设置为Clear And Copy All(自动创建StreamingAssets\yoo,将所有资源包复制到该目录下)
如下是一个使用ResourceSys的例子(具体代码见后文):
在Launch场景(唯一需要Build的场景)中有一Launcher,在其中初始化ResourceSys。完成后载入并进入目标场景,进入后游戏开始:载入预制体并创建副本、载入并播放音效、载入并将精灵图显示在Image上。说明:在编辑器模式下,载入音效会报错,无法播放。但是打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加载
说明
- 先将所有资源放到Resources下,通过Resources加载:需传入相对Resources的路径,而非资源名称。
- 需要把场景添加到BuildSettings中。
- 所有资源都通过FanResourceSys加载,而不是直接调用Resources.Load。
- 方便后续将资源放在远端,修改加载方式。
使用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
}