内置的资源,如精灵、shader、材质、字体等,怎么用代码去访问?
在编辑器中,可以用AssetDatabase.GetBuiltinExtraResource访问,只是传入的path比较迷,可以说不是path,只是一个key。
具体的path可以网上查得到,比如那几个精灵的path,在ugui的源码中可以找到。
key在哪里定义的?这个就说不清了,可能是资源管理器初始化时写的这么一些特定的path。
运时的的API:Resources.GetBuiltinResource就更是晦涩了,API文档上也没有提及,网上能查到关于它的使用都是加载内置的字体或者材质。
经过长久的尝试,传入各种key,但是精灵是始终加载不出来。
也试过在Editor中拿到对象后,在Resources目录下创建一个asset,也提示资源已存在。
其实在Unity安装路径下的Editor\Data\Resources下,我们可以看到那个文件:unity_builtin_extra,另外,用Unity安装目录中的binary2text.exe也可以把这个二进制文件转成文本格式。可以看到里面是YAML那一套,有shader,有网格,有图片,等等。。对应的数据也是直接嵌在里面的。这个就涉及到子资源的概念了,也就是同一个路径下,可以有多个对象,因为它们是序列化在一个.asset文件中的。
说了这么多,但是最终还是没有通过上面的接口加载到精灵,可能它就没有一个可控查询的名字。
另外内置资源在发布时肯定会按需裁剪的,因为它本身有几十M。
最后转换思路,用的ScriptObject引用内置资源解决的。这种方案好处是:
1、没有用到一些非公开的API和路径,这些很可能变动。
2、在Editor中的接口可以访问内置资源,因此可以全代码、自动化。
3、引用不会造成资源重复。
核心代码很简单:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Serialize3rd
{
[CreateAssetMenu(fileName = "BuiltinResRef")]
public class BuiltinResRef : ScriptableObject
{
public List<UnityEngine.Object> List;
public void Add(UnityEngine.Object res)
{
if (List == null)
List = new List<UnityEngine.Object>();
if (List.Contains(res))
return;
else
List.Add(res);
}
public UnityEngine.Object Load(Type t, string name)
{
foreach (var i in List)
{
if (i != null && i.GetType() == t && i.name == name)
return i;
}
Debug.LogErrorFormat("对内置资源的引用中不存在{0},Type:{1}", name, t);
return null;
}
}
}
然后,如果是在编辑器脚本中增加对内置资源的引用,代码段如下:
if (builtinRef == null)
{
builtinRef = Resources.Load<BuiltinResRef>(Path.Combine(Utility.ResDir, Utility.BuiltinRefName));
if (builtinRef == null)
{
builtinRef = ScriptableObject.CreateInstance<BuiltinResRef>();
AssetDatabase.CreateAsset(builtinRef, Path.Combine("Assets", ResFolder, Utility.ResDir, Utility.BuiltinRefName + ".asset"));
}
}
builtinRef.Add(res);
UnityEditor.EditorUtility.SetDirty(builtinRef);
AssetDatabase.SaveAssets();