我希望用户能够在播放模式之外创建我的 ScriptableObject 资产,以便他们可以将它们绑定到场景中的对象。由于我不希望 Zenject 创建 ScriptableObjects,因此工厂解决方案不是我想要的。因此,我必须以某种方式将这些脚本对象的实例提供给 Zenject 安装程序并使用“QueueForInject”。这是我发现的两种方法:
A) 通过检查器窗口手动将这些脚本对象添加到安装程序。例子:
public class GameInstaller : MonoInstaller<GameInstaller>
{
// Visible in the inspector window so user can add Script Objects to List
public List<ScriptableObject> myScriptObjectsToInject;
public override void InstallBindings()
{
foreach (ScriptableObject scriptObject in myScriptObjectsToInject)
{
Container.QueueForInject(scriptObject);
}
}
}
B) 使用 Unity 的 AssetDatabase 和 Resources API 查找所有脚本对象实例,然后遍历列表到 QueueForInject。例子
// search for all ScriptableObject that reside in the 'Resources' folder
string[] guids = AssetDatabase.FindAssets("t:ScriptableObject");
foreach (string guid in guids)
{
// retrieve the path string to the asset on disk relative to the Unity project folder
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
// retrieve the type of the asset (i.e. the name of the class, which is whatever derives from ScriptableObject)
System.Type myType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
//Find the relative path of the asset.
string resourcesDirectoryName = $"/Resources/";
int indexOfLastResourceDirectory = assetPath.LastIndexOf(resourcesDirectoryName) + resourcesDirectoryName.Length;
int indexOfExtensionPeriod = assetPath.LastIndexOf(".");
string assetPathRelative = assetPath.Substring(indexOfLastResourceDirectory, indexOfExtensionPeriod - indexOfLastResourceDirectory);
//Grab the instance of the ScriptableObject.
ScriptableObject scriptObject = Resources.Load(assetPathRelative, myType) as ScriptableObject;
if (scriptObject == null)
{
Debug.LogWarning(
"ScriptableObject asset found, but it is not in a 'Resources' folder. Current folder = " +
assetPath);
continue;
}
else
{
Container.QueueForInject(scriptObject);
}
}
对于选项 A),最终用户必须记住手动将脚本对象放置在他们创建的每个新脚本对象的列表中。我宁愿找到一种自动化的方式,这样用户就不必知道/记住这个额外的手动过程。
使用选项 B) 我得到了一个很棒的自动化解决方案。但最终用户必须记住将每个 ScriptableObject 资产文件存储在名为“Resources”的目录中,因为这是 Resources.Load API 找到实例的唯一方式。如果找不到,我可以警告用户,这很好。但他们仍然被迫遵守以删除警告。
如果必须,我可以接受选项 B,但我真的想更进一步,让它对最终用户完全不可见。有没有人为 Play Mode 之外存在的 ScriptObjects 提出了一个更巧妙的自动化解决方案?