Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How can Components get notified their Prefab was edited?

Discussion in 'Prefabs' started by Thygrrr, Nov 7, 2018.

  1. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    699
    I really, really love the new prefab workflow and absolutely am not looking back, ever. Great job, Unity!

    Now, to pose a question: I'm using (and developing) some editor extensions, that generate meshes based on data held in a component (Monobehaviour-derived).

    If I edit a prefab where the object itself or a child have these components on them (e.g. prefab mode, or using Apply Values to Prefab), all (other) instances will not update until I reload the scene or manually open the custom editor for each. (other in parentheses because I am technically automatically opening the editor for that when I come back from prefab mode)

    I'm trying to extend these editors to work well with the new prefabs, but I wonder what callbacks are invoked on which objects in the cases when:
    • the prefab for this instance is changed / values applied
    • the prefab that contains this child object is changed
    Also, how do I know my component is part of a prefab, prefab variant, or has changes from the existing prefab? (the components generate custom meshes and materials, and of course I'd like to keep their numbers down when using prefabs where possible)
     
    Last edited: Nov 7, 2018
  2. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Are you saying the changes to the properties are not propagated to the instances or that your component is not regenerating the mesh?
     
  3. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    699
    The component isn't regenerating the mesh, because it doesn't "know" that its values were updated.

    This will likely be a simple custom editor OnSomething method implementation, but I haven't found the right documentation for it so far.

    I'll try OnValidate()

    EDIT: OnValidate works very well. Some confusion with (Nested) Prefab Variants but I assume I don't fully understand Variants and Nesting at this point. (I do get a lot of "Bold" font and options to apply changes to prefabs, even though they were freshly added to the scene, so I guess the code I am porting re-generates some serialized data in Awake etc.)
     
    Last edited: Nov 7, 2018
  4. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    I suggest generating the mesh in Awake. OnValidate has a different purpose.
     
    Thygrrr likes this.
  5. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    699
    This talk helped a LOT figuring out what I can do with the prefabs etc.

     
  6. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    699
    So awake gets called each time the Prefab changes? Then I wonder why the code didn't work before.
     
  7. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    699
    Debugging shows me:
    Awake() is called when I enter Prefab Mode.

    Awake() is NOT called when I come back into the scene view from prefab mode, where other instances of this prefab sit, and thus these do not get a chance to regenerate their meshes based on the updated prefab data. (they do have the right data)

    However, abusing OnValidate() works exactly for this purpose; is there another function that gets called in this scenario?
     
    Last edited: Nov 7, 2018
  8. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Hi,

    I really don't think you should use OnValidate :)

    The reason Awake does not work is because you need to add [ExecuteAlways] to your script.
    But after having tested myself I realized I was wrong. What you get during merge is OnEnable, so that could be an option.

    Probably even better is https://docs.unity3d.com/2018.3/Doc...ence/PrefabUtility-prefabInstanceUpdated.html then you don't need [ExecuteAlways] on you script.
     
    Thygrrr likes this.
  9. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    699
    I've used prefabInstanceUpdated, but I suppose that gets called for every prefab instance in the scene, so I am wary to put anything complex in there.

    I've also been struggling to identify whether my gameobject was part of a prefab to know whether I should recalculate the mesh.

    I'll look into OnEnable. :)

    Conversely, the opposite case is also an issue - knowing when an object becomes or will become connected to a prefab, to prepare it (e.g. to write out meshes as assets)

    Related topic: https://forum.unity.com/threads/delegate-when-object-is-converted-to-prefab.580888/