动态加载资源之AssetDatabase

本文介绍如何使用Unity Editor的AssetDatabase类监听资源变动,并创建资源映射.txt文件。此外,通过ResLoaderManager实现动态加载和资源路径管理,包括Sprite和GameObject的获取。
摘要由CSDN通过智能技术生成

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;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值