【发布时间】:2016-12-11 18:07:08
【问题描述】:
这是对this question的跟进
假设我有一个简单的 MonoBehaviour
public class FooScript : MonoBehaviour {
public int someValue = 0;
public int otherValue = 0;
}
我把它放在一个空的游戏对象上,然后将游戏对象拖到项目中以创建一个预制件。
如果我选择预制件并编辑 someValue,那么如果我转到仍在场景中的实例,我会看到 someValue 已更新。
如果我在实例上编辑someValue,那么更新预制件上的someValue someValue 不会在实例上更新,但如果我在预制件上更新otherValue,它会更新实例。换句话说,每个实例属性都有自己的标志,是否已从源预制件修改。
但是,如果我创建一个编辑器脚本并在预制件上查找FooScript 并设置someValue,则实例未更新,只有预制件。我希望它的行为就像我在编辑器中手动完成一样。换句话说,如果实例属性已被用户编辑,则不要更新。如果实例属性尚未编辑,请更新。
问题是这样做的正确方法是什么?查看PrefabUtilily 似乎没有ApplyPropertiesFromSourcePrefabOnAllUnmodifiedInstancePropreties 函数。
我能想到的唯一解决方案听起来极度令人费解。我不得不
- 查找所有实例(遍历整个层次结构,不确定在未加载的场景中会发生什么)
- 通过调用
PrefabUtility.GetPropertyModifications并将结果存储在一些Dictionary<GameObject, PropertyModifications[]>中,对每个实例记录进行修改。 (大量内存) - 将我的更改应用到预制件。
- 然后,对于每个没有修改我正在更新的字段的实例,也要更新实例上的该属性。
真的那么复杂还是有更简单的方法?
【问题讨论】:
-
如果你使用
PrefabUtility.MergeAllPrefabInstances()会发生什么? -
令人惊讶的是这似乎有效,但文档说“这是自动完成的,您不必手动调用此函数。”这表明我应该这样做别的东西。呼叫尝试呼叫
EditorUtilitiy.SaveDirty(prefabGameobject),这似乎更合适? -
你的意思是
EditorUtility.SetDirty(Object)?该文档还说您不应该使用它。 -
是的,我就是这个意思。我看不出它在哪里说不要调用它。实际上它说“例如,如果您修改 prefab 的 MonoBehaviour 或 ScriptableObject 变量,您必须告诉 Unity 该值已更改。”
-
引用文档:''在 Unity 5.3 之前,这是将对象标记为脏的主要方法。从 5.3 开始,随着多场景编辑的引入,该功能不再用于修改场景中的对象。相反,您应该在对对象进行更改之前使用 Undo.RecordObject。这会将对象的场景标记为脏,并在编辑器中提供一个撤消条目。''