Search Unity

New prefab system and AssetModificationProcessors

Discussion in 'Prefabs' started by liortal, Oct 11, 2019.

  1. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    In our project, we built a custom "verification" system by using the AssetModificationProcessor class -
    whenever an asset is saved (scene / prefab) we run a bunch of tests on it to verify some conditions are met.

    With the new prefab system, as far as i can see, there are currently 2 ways of modifying a prefab:
    1. Prefab mode (i guess this is how god intended us to edit them from now on?)
    2. By overriding certain properties and applying those overrides (via the inspector).
    With the first approach, my asset modification processor does something like this (BTW where are the docs regarding APIs of the new prefab system? couldn't find anything helpful):
    Code (CSharp):
    1.  // Check if the prefab is saved from the prefab window.
    2. var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
    3.  
    4. if (prefabStage != null)
    5. {
    6.     // get prefabStage.prefabContentsRoot
    7.     // run verification here
    8. }
    My question is - how do i detect use case #2 ? in that case, i get a callback that the prefab is going to be saved (and the path to it) but how do i get the actual GameObject to run my verifications on ?
     
    Last edited: Oct 11, 2019
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
  3. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Are you sure this is what I need?
    In this case, the prefab aas not saved to disk yet so I am not sure loading it from its path will return the modified one.
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
  5. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Just tried your suggestion @Baste . Unfortunately, the AssetModificationProcessor is called first and so there's no way to get the prefab's GameObject root before it gets saved to disk.
     
  6. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Perhaps instead of using an AssetModificationProcessor, you could use an AssetPostprocessor instead? Like:
    https://docs.unity3d.com/ScriptReference/AssetPostprocessor.OnPostprocessAllAssets.html

    This way you get a callback after the Prefab has already been saved and imported, and you can verify it then. This would be the Prefab Asset, as opposed to the Prefab content as you currently get with the prefabContentsRoot, but if you need to modify it as content, you can always use PrefabUtility.LoadPrefabContents etc. If you make modifications, it will trigger new imports, so it's important to be deterministic to not trigger an endless import loop.

    Also note that when a Prefab is reimported, any other Prefabs that are Variants of it or has it as a nested Prefab will get reimported too, and they will all be included in the OnPostprocessAllAssets callback in no particular order.
     
  7. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Thanks for the answer @runevision
    It is 'kind of' possible to do it that way.

    BUT.... what we're trying to prevent is saving of prefabs / scenes that did not meet a certain set of criteria (e.g: tests). Reacting to it only AFTER it was saved means we are saving an invalid asset, which is not what i'd like to have.
     
  8. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    All right. I'm afraid that to my knowledge there's no way to intercept applying Prefab overrides.
     
  9. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    The only 'hacky' way I can think of is to search the hierarchy for a 'modified' instance of the prefab being saved. Not sure if that is even possible, there may be multiple instances and u am not sure I can detect which is the one that was saved.
     
  10. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    In order to apply modifications you need to select the prefab instance in the hierarchy so the update button gets shown in the inspector. Also applying modifications from multiple objects is not supported. Maybe you can get the prefab instance being modified via Selection API ?
     
    liortal likes this.
  11. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    interesting idea, i will look into that :)