为了方便程序中动态加载resources目录中物体,编写了一个ResourceManager的单例类,使用时需要将其附加到一个游戏物体上。
可以实现对物体的分类、重命名、异步加载。
可用方法如下:
//通过名字和类型加载,类型为0时,不判断类型
ResourceRes<T> Load<T>(string name, ResourceType type = 0) where T : UnityEngine.Object
//通过名字和类型加载所有,类型为0时,不判断类型
T[] LoadAll<T>(string name, ResourceType type = 0) where T : UnityEngine.Object
//通过类型加载所有,可以用与的方式,例如加载两个类型:(ResourceType.BGM|ResourceType.Model)
ResourceRes<T>[] LoadAllFromTypeMask<T>(int typeMask) where T : UnityEngine.Object
//异步通过类型加载所有
public void LoadAllFromTypeMaskAsync<T>(int typeMask, Action<ResourceRes<T>[]> onComplete) where T : UnityEngine.Object
//异步通过名字和类型加载所有
void LoadAsync<T>(string name, Action<ResourceRes<T>> onComplete, ResourceType type = 0) where T : UnityEngine.Object
使用方式:
GameObject obj = ResourceManager.Instance.Load<GameObject>("Main").res;
ResourceManager.Instance.LoadAsync<GameObject>("Main", (res) =>
{
if (res != null)
{
GameObject obj = res.res;
}
});
源码如下:
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
using System.IO;
#endif
public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
private static T _Instance;
public static T Instance
{
get
{
if (_Instance == null)
{
_Instance = FindObjectOfType<T>();
}
return _Instance;
}
}
}
//物体分类,一个物体可以是多种类型
public enum ResourceType
{
BGM = 0x0001,
Model = 0x0002,
Scene = 0x0004,
PromptAudio = 0x0008,
}
[System.Serializable]
public class ResourceItem
{
public string name;//资源名字
public string path;//资源resources路径
public ResourceType type;//资源类型
public ResourceItem(string name, string path, ResourceType type)
{
this.name = name;
this.path = path;
this.type = type;
}
}
[Serializable]
public class ResourceRes<T> where T : UnityEngine.Object
{
public string name;//资源名字
public T res;//资源
public ResourceRes(string name, T res)
{
this.name = name;
this.res = res;
}
}
[Serializable]
public class ResourceList
{
public List<ResourceItem> value = new List<ResourceItem>();
}
public class ResourceManager : Singleton<ResourceManager>
{
/// <summary>
/// 资源配置文件
/// </summary>
private string _configFilePath = "configs/resourcemanager";
public ResourceList _resLst;
public void Awake()
{
LoadConfig();
}
private void LoadConfig()
{
TextAsset config = Resources.Load<TextAsset>(_configFilePath);
if (null == config)
{
Debug.LogError("LoadConfig config is null");
return;
}
if (string.IsNullOrEmpty(config.text))
{
Debug.LogError("LoadConfig config.text is null or empty.");
return;
}
_resLst = JsonUtility.FromJson<ResourceList>(config.text);
Debug.Assert(null != _resLst, "LoadConfig _audioResLst is null.");
}
private ResourceItem GetItemFromName(ResourceList resLst, string name)
{
ResourceItem item = resLst.value.Find((rt) =>
{
return rt.name == name;
});
return item;
}
private ResourceItem GetItemFromNameType(ResourceList resLst, string name, ResourceType type)
{
ResourceItem item = resLst.value.Find((rt) =>
{
return (rt.name == name) && (rt.type == type);
});
return item;
}
private List<ResourceItem> GetAllResourceItemFromTypeMask(ResourceList resLst, int typeMask)
{
return resLst.value.FindAll((t) =>
{
return (((int)t.type & typeMask) != 0);
});
}
public ResourceRes<T> Load<T>(string name, ResourceType type = 0) where T : UnityEngine.Object
{
ResourceItem item = null;
if (0 == type)
{
item = GetItemFromName(_resLst, name);
}
else
{
item = GetItemFromNameType(_resLst, name, type);
}
if (null == item)
{
return null;
}
T t = Resources.Load<T>(item.path);
Debug.Assert(t != null, "srcpath:" + item.path);
return new ResourceRes<T>(name, t);
}
public void LoadAsync<T>(string name, Action<ResourceRes<T>> onComplete, ResourceType type = 0) where T : UnityEngine.Object
{
StartCoroutine(AsyncLoading<T>(_resLst, name, onComplete, type));
}
public T[] LoadAll<T>(string name, ResourceType type = 0) where T : UnityEngine.Object
{
ResourceItem item = null;
if (0 == type)
{
item = GetItemFromName(_resLst, name);
}
else
{
item = GetItemFromNameType(_resLst, name, type);
}
if (null == item)
{
return null;
}
T[] t = Resources.LoadAll<T>(item.path);
Debug.Assert(t != null, "srcpath:" + item.path);
return t;
}
public ResourceRes<T>[] LoadAllFromTypeMask<T>(int typeMask) where T : UnityEngine.Object
{
ResourceRes<T>[] obj = null;
List<ResourceItem> resItemLst = GetAllResourceItemFromTypeMask(_resLst, typeMask);
Debug.Assert(null != resItemLst, "resItemLst is Null");
if (null != resItemLst)
{
List<ResourceRes<T>> tempLst = new List<ResourceRes<T>>();
T tempObj = null;
foreach (ResourceItem item in resItemLst)
{
tempObj = Resources.Load<T>(item.path);
Debug.Assert(null != tempObj, "tempObj is Null");
if (null != tempObj)
{
tempLst.Add(new ResourceRes<T>(item.name, tempObj));
}
}
obj = tempLst.ToArray();
}
return obj;
}
public void LoadAllFromTypeMaskAsync<T>(int typeMask, Action<ResourceRes<T>[]> onComplete) where T : UnityEngine.Object
{
StartCoroutine(AsyncLoadingAllFromTypeMask<T>(_resLst, typeMask, onComplete));
}
private IEnumerator AsyncLoadingAllFromTypeMask<T>(ResourceList resLst, int typeMask, Action<ResourceRes<T>[]> onComplete) where T : UnityEngine.Object
{
List<ResourceItem> resItemLst = GetAllResourceItemFromTypeMask(resLst, typeMask);
yield return AsyncLoadingAllFromItems<T>(resItemLst.ToArray(), onComplete);
}
private IEnumerator AsyncLoadingAllFromItems<T>(ResourceItem[] resLst, Action<ResourceRes<T>[]> onComplete) where T : UnityEngine.Object
{
ResourceRes<T>[] obj = null;
Debug.Assert(null != resLst, "itemLst is Null");
bool nextStep = false;
if (null != resLst)
{
List<ResourceRes<T>> tempLst = new List<ResourceRes<T>>();
foreach (ResourceItem item in resLst)
{
nextStep = false;
while (!nextStep)
{
yield return AsyncLoading<T>(item, (t) =>
{
if (null != t)
{
tempLst.Add(t);
}
nextStep = true;
});
}
}
obj = tempLst.ToArray();
}
if (null != onComplete)
{
onComplete(obj);
}
}
private IEnumerator AsyncLoading<T>(ResourceItem item, Action<ResourceRes<T>> onComplete) where T : UnityEngine.Object
{
T obj = null;
Debug.Assert(null != item, "item is Null");
if (!string.IsNullOrEmpty(item.path))
{
ResourceRequest req = Resources.LoadAsync<T>(item.path);
Debug.Assert(req != null, "srcpath:" + item.path);
if (req != null)
{
while (!req.isDone)
{
yield return null;
}
obj = req.asset as T;
}
}
else
{
Debug.Log("srcpath is Null or Empty");
}
if (null != onComplete)
{
onComplete(new ResourceRes<T>(item.name, obj));
}
yield return null;
}
private IEnumerator AsyncLoading<T>(ResourceList resLst, string name, Action<ResourceRes<T>> onComplete, ResourceType type = 0) where T : UnityEngine.Object
{
ResourceItem item = null;
if (0 == type)
{
item = GetItemFromName(resLst, name);
}
else
{
item = GetItemFromNameType(resLst, name, type);
}
yield return AsyncLoading(item, onComplete);
}
}
#if UNITY_EDITOR
//编辑器扩展
[CustomEditor(typeof(ResourceManager))]
[CanEditMultipleObjects()]
public class ResourceManagerEdit : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("Edit Config"))
{
ResourceManagerWindow.ShowWindow();
}
}
}
public class ResourceManagerWindow : EditorWindow
{
[MenuItem("Custom/Resource Mgr")]
public static void ShowWindow()
{
ResourceManagerWindow window = GetWindow<ResourceManagerWindow>("Resource Mgr");
window.Show();
}
[Serializable]
public class ResourceManagerConfig
{
public string configPath = "resources/configs/resourcemanager";
}
string editConfigPath = "";
ResourceManagerConfig editConfig = null;
ResourceList _lst = null;
public void OnEnable()
{
editConfigPath = Path.Combine(Application.dataPath, "../ProjectSettings/ResourceManagerConfig.json");
if (File.Exists(editConfigPath))
{
string editConfigMsg = File.ReadAllText(editConfigPath);
editConfig = JsonUtility.FromJson<ResourceManagerConfig>(editConfigMsg);
}
if (null == editConfig)
{
editConfig = new ResourceManagerConfig();
}
Load();
}
public void OnDisable()
{
Save();
string editConfigMsg = JsonUtility.ToJson(editConfig);
File.WriteAllText(editConfigPath, editConfigMsg);
}
void Load()
{
string path = Path.Combine(Application.dataPath, editConfig.configPath);
if (File.Exists(path))
{
string configMsg = File.ReadAllText(path);
_lst = JsonUtility.FromJson<ResourceList>(configMsg);
}
if (null == _lst)
{
_lst = new ResourceList();
}
}
void Save()
{
if (!string.IsNullOrEmpty(editConfig.configPath))
{
string path = Path.Combine(Application.dataPath, editConfig.configPath);
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
}
string configMsg = JsonUtility.ToJson(_lst);
File.WriteAllText(path, configMsg);
if (File.Exists(path))
{
AssetDatabase.ImportAsset("Assets/" + editConfig.configPath, ImportAssetOptions.ForceSynchronousImport);
}
}
}
Vector2 _scrollPos;
public void OnGUI()
{
GUILayout.Label("Root is Assets folder path.");
GUILayout.BeginHorizontal();
GUILayout.Label("Path:", GUILayout.MaxWidth(50));
editConfig.configPath = GUILayout.TextField(editConfig.configPath);
if (GUILayout.Button("Load", GUILayout.Width(40), GUILayout.Height(14)))
{
Load();
}
GUILayout.EndHorizontal();
GUILayout.BeginVertical();
GUILayout.BeginHorizontal();
GUILayout.Label("Name:", GUILayout.Width(100));
GUILayout.Label("Path:");
GUILayout.Label("Type:", GUILayout.Width(100));
GUILayout.EndHorizontal();
_scrollPos = GUILayout.BeginScrollView(_scrollPos);
for (int index = 0, cnt = _lst.value.Count; index < cnt; index++)
{
GUILayout.BeginHorizontal();
ResourceItem item = _lst.value[index];
item.name = GUILayout.TextField(item.name, GUILayout.Width(100));
item.path = GUILayout.TextField(item.path);
item.type = (ResourceType)EditorGUILayout.EnumMaskField(item.type, GUILayout.Width(100));
if (GUILayout.Button("-", GUILayout.Width(20), GUILayout.Height(14)))
{
_lst.value.RemoveAt(index);
--index;
--cnt;
continue;
}
GUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
if (GUILayout.Button("Add"))
{
_lst.value.Add(new ResourceItem("", "", 0));
}
GUILayout.EndVertical();
}
}
#endif
作者:u012741077 发表于2016/11/27 19:46:31 原文链接
阅读:37 评论:0 查看评论