AssetDatabase类声明在UnityEditor命名空间内;它用于访问资源以及对资源执行一些操作,主要是对Project面板下的资源进行增删改查操作,它仅仅可以在编辑器模式中使用,用于开发者自身的工具扩展。具体使用方法如下:
①首先监听资源变动消息,生成一个.txt文件保存资源映射
using System.IO;
using UnityEditor;
using UnityEngine;
public class AssetPostprocessorEvent : AssetPostprocessor
{
//所有的资源的导入,删除,移动,都会调用此方法
public static void OnPostprocessAllAssets(string[] importedAsset, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
CreateAssetsMapTxt();
}
/// <summary>
/// 创建一个.txt文件,来记录资产映射
/// </summary>
private static void CreateAssetsMapTxt()
{
string assetsMapPath = ConstCfg.assetsMapPath;
FileStream fs = null;
if (!File.Exists(assetsMapPath))
{
//没有则创建这个文件
fs = new FileStream(assetsMapPath, FileMode.Create, FileAccess.Write);//创建写入文件
File.SetAttributes(assetsMapPath, FileAttributes.Hidden); //设置文件属性为隐藏
}
else
{
File.Delete(assetsMapPath);
fs = new FileStream(assetsMapPath, FileMode.Create, FileAccess.Write);//创建写入文件
File.SetAttributes(assetsMapPath, FileAttributes.Hidden); //设置文件属性为隐藏
}
StreamWriter sw = new StreamWriter(fs);
string strAllAssetsRoot = Application.dataPath + '/' + "Game";
DirectoryInfo dirTempInfo = new DirectoryInfo(strAllAssetsRoot);
DirectoryInfo[] directoryDIRArray = null;
directoryDIRArray = dirTempInfo.GetDirectories();
foreach (DirectoryInfo currentDir in directoryDIRArray)
{
//2.1:遍历本场景目录下所有的目录或者文件
// 如果是目录,则继续“递归”访问里面的文件,直到定位到文件
string tmpScenesDir = strAllAssetsRoot + "/" + currentDir.Name; // Unity /xx/xx 全路径
int tmpIndex = tmpScenesDir.LastIndexOf("/");
string tmpScenesName = tmpScenesDir.Substring(tmpIndex + 1); // 场景名称
//Debug.Log("tmpScenesDir = "+ tmpScenesDir);
//2、2 递归调用方法,找到文件,则使用 AssetImporter 类,标记“包名”与 “后缀名”
JudgeDirOrFileByRecursive(currentDir,sw);
}
sw.Close();
fs.Close();
}
/// <summary>
/// 递归判断判断是否是目录或文件
/// 是文件,记录到.txt中
/// 是目录,则继续递归
/// </summary>
/// <param name="fileSystemInfo">当前文件信息(文件信息与目录信息可以相互转换)</param>
private static void JudgeDirOrFileByRecursive(FileSystemInfo fileSystemInfo, StreamWriter sw)
{
// 参数检查
if (fileSystemInfo.Exists == false)
{
Debug.LogError("文件或者目录名称:" + fileSystemInfo + " 不存在,请检查");
return;
}
// 得到当前目录下一级的文件信息集合
DirectoryInfo directoryInfoObj = fileSystemInfo as DirectoryInfo; // 文件信息转为目录信息
FileSystemInfo[] fileSystemInfoArray = directoryInfoObj.GetFileSystemInfos();
foreach (FileSystemInfo fileInfo in fileSystemInfoArray)
{
FileInfo fileInfoObj = fileInfo as FileInfo;
// 文件类型
if (fileInfoObj != null)
{
sw.WriteLine(fileInfoObj.Name + "|" + fileInfoObj.FullName);//开始写入值W
}
// 目录类型
else
{
// 如果是目录,则递归调用
JudgeDirOrFileByRecursive(fileInfo, sw);
}
}
}
}
②记录固定字段的表(个人习惯,不单独列出来也可以)
using UnityEngine;
public static class ConstCfg
{
public static string assetsMapPath = Application.dataPath + "/assetsMap.txt";//资源映射文件存储路径
}
③资源加载管理类
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
//动态加载资源管理类
public class ResLoaderManager : SingletonBase<ResLoaderManager>
{
Dictionary<string,string> assetsPathMap = new Dictionary<string,string>();
/// <summary>
/// 初始化资源映射字典
/// </summary>
public void InitAssetsMap()
{
string assetsMapPath = ConstCfg.assetsMapPath;
if (!File.Exists(assetsMapPath))
{
Debug.Log("缺少资源映射文件:" + assetsMapPath);
}
else
{
string[] temp = File.ReadAllLines(assetsMapPath);
foreach (var item in temp)
{
assetsPathMap.Add(item.Split('|')[0].Split('.')[0], item.Split('|')[1]);
}
}
}
/// <summary>
/// 获得Sprite资源
/// </summary>
/// <param name="assetName">资源名称</param>
/// <returns></returns>
public Sprite GetSprite(string assetName)
{
return GetAssets<Sprite>(assetName);
}
/// <summary>
/// 获得GameObject资源
/// </summary>
/// <param name="assetName">资源名称</param>
/// <returns></returns>
public GameObject GetGameObject(string assetName)
{
return GetAssets<GameObject>(assetName);
}
/// <summary>
/// 获得资源
/// </summary>
/// <typeparam name="T">资源类型</typeparam>
/// <param name="assetName">资源名称</param>
/// <returns></returns>
private T GetAssets<T>(string assetName) where T : Object
{
#if UNITY_EDITOR
return GetAssetsInEDITOR<T>(assetName);
#else
#endif
}
/// <summary>
/// 在编辑器模式下加载资源
/// </summary>
/// <typeparam name="T">资源类型</typeparam>
/// <param name="assetName">资源名称</param>
/// <returns></returns>
private T GetAssetsInEDITOR<T>(string assetName) where T : Object
{
if (typeof(T) == typeof(Sprite))
{
Texture2D _asset = AssetDatabase.LoadAssetAtPath<Texture>(assetsPathMap[assetName]) as Texture2D;
Sprite sprite = Sprite.Create(_asset, new Rect(0, 0, _asset.width, _asset.height), Vector2.zero);
return sprite as T;
}
return AssetDatabase.LoadAssetAtPath<T>(assetsPathMap[assetName]);
}
}
④测试代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
GetComponent<Image>().sprite = ResLoaderManager.Instance.GetSprite("图片资源名");
Instantiate(ResLoaderManager.Instance.GetGameObject("预制体名"));
}
// Update is called once per frame
void Update()
{
}
}
⑤最后附上ResLoadManager.cs继承的类
public class SingletonBase<T> where T : new()
{
private static T instance;
// 多线程安全机制
private static readonly object locker = new object();
public static T Instance
{
get
{
if (instance == null)
{
//lock写第一个if里是因为只有该类的实例还没创建时,才需要加锁,这样可以节省性能
lock (locker)
{
if (instance == null)
instance = new T();
}
}
return instance;
}
}
}