所以一些上下文:
我目前正在 Unity 中使用 EditorWindow 来制作自定义规则系统。这个规则系统由一堆派生自 ScriptableObject 的类组成,因此我可以创建它们的实例并仍然在那个窗口中访问它们。 (我花了很长时间才让它工作,因为我开始时没有使用 ScriptableObjects)
拥有整个规则系统的资产称为 Ruleset,它本身也是一个 ScriptableObject。我基本上只是替换了规则集 ScriptableObject 的检查器,给我一个按钮来打开 EditorWindow,然后我可以在其中立即编辑整个规则集。
为了组织整个事情,我这样做是为了在该规则集中创建一个新规则:
Rule newRule = CreateInstance<Rule>();
// currentRuleset is the SerializedObject of the Ruleset, so it's targetObject is the ruleset ScriptableObject
AssetDatabase.AddObjectToAsset(newRule, currentRuleset.targetObject);
// Reimport the new Asset so it shows up in the UnityEditor
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(newRule));
这部分效果很好。所有规则都显示为 Ruleset-ScriptableObject 的子资产。然后我将它添加到规则集中的列表中并应用修改后的属性,这样它就全部保存了。
现在我的问题:
当我想从该规则集中删除一个规则时,我发现实现这一目标的唯一方法是从资产中删除对象并销毁它,所以我执行以下操作:
// ruleList is the SerializedProperty of a List<Rule> in the ruleset, so accessing values inside it is a bit fidilly
// Remove the last rule SubAsset from the ruleset mainAsset
AssetDatabase.RemoveObjectFromAsset(ruleList.GetArrayElementAtIndex(ruleList.arraySize - 1).objectReferenceValue);
// Destroy the rule ScriptableObject so it is actually deleted
DestroyImmediate(ruleList.GetArrayElementAtIndex(ruleList.arraySize - 1).objectReferenceValue, true);
currentRuleset.ApplyModifiedProperties(); // <- currentRuleset is the SerializedObject of the ruleset
// Reimport the mainAsset so the changes show up in the UnityEditor
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(currentRuleset.targetObject));
这也有效,但是,每次我从规则集中删除规则时,Unity 都会向我发出警告,因为 ImportAsset-Command:
Importer(NativeFormatImporter) 为 asset(guid:e23e75a89de672045aeaa42eeb54b26e) 生成了不一致的结果
有没有更好的方法来做到这一点?如果我删除导入命令,更改将不会显示在 Unity 中,直到我重新导入或再次编译。 (当我手动重新导入资产时,我也会收到此警告)
使用:
AssetDatabase.SaveAssets();
实际上用适当的剩余子资产更新父资产(以及项目中所有其他未保存的资产)。它不会(至少在我的设置中)触发 AssetDatabase.ImportAsset() 似乎触发的不一致错误。
还有
AssetDatabase.SaveAssetIfDirty(parentObject);
我没有设法通过这种方法获得一致的结果,并且经常需要重新导入对象(有时会触发不一致警告)。
供参考,以防有人遇到同样的问题:根据我的观察,一旦不一致警告出现在对象上,任何代码或手动编辑器重新导入该特定对象每次都会再次触发它。我发现解决它的唯一方法肯定是清除主要资产的所有子资产,方法是遍历 AssetDatabase.LoadAllAssetRepresentationsAtPath() 返回的列表。