user128511
user128511

Reputation:

How to update a prefab property from editor script and have the instances get the updates?

This is a follow up to this question

Assume I have a simple MonoBehaviour

public class FooScript : MonoBehaviour {
  public int someValue = 0;
  public int otherValue = 0;
}

I put that on an empty GameObject then drag the GameObject to the Project to create a prefab.

If I select the prefab and edit someValue then if I go to the instance still in the scene I see someValue is updated.

If I edit someValue on the instance then update someValue on the prefab someValue is NOT updated on the instance but if I update otherValue on the prefab it does update on the instance. In other words each instance property has it's own flag on if it has been modified from the source prefab or not.

But, if I make an editor script and lookup FooScript on the prefab and set someValue the instance is NOT updated, only the prefab. I want it to act exactly as if I had done it manually in the editor. In other words, if the instance property has been edited by the user don't update. If instance property has not been edited do update.

The question is what's the correct way to do that? Looking at PrefabUtilily there doesn't appear to be a ApplyPropertiesFromSourcePrefabOnAllUnmodifiedInstancePropreties function.

The only solution I can think of sounds EXTREMELY convoluted. I'd have to

  1. find all instances (walk the entire hierarchy, not sure what happens in unloaded scenes)
  2. for each instance record the modifications are on it by calling PrefabUtility.GetPropertyModifications and storing the results in some Dictionary<GameObject, PropertyModifications[]>. (lots of memory)
  3. Apply my change to the prefab.
  4. Then, for every instance that doesn't have a modification to the field I'm updating update the that property on instance as well.

Is it really that convoluted or is there some easier way?

Upvotes: 3

Views: 9415

Answers (1)

Isaac van Bakel
Isaac van Bakel

Reputation: 1852

From a Documentation browse, it looks like Unity expects you to use Undo.RecordObject(Object objectToUndo, string name) in code before you modify a property on the prefab, which will also have the benefit of creating an Undo step in Unity itself so that you can revert any changes.

You can use EditorUtility.SetDirty(Object), but only if you don't want to create an Undo step, and the Unity docs specifically recommend against it.

Upvotes: 1

Related Questions