Search Unity

How to programmatically open prefab for edit using a specific scene as the stage environment

Discussion in 'Prefabs' started by Prodigga, Feb 25, 2019.

  1. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Hi there

    There is an example on the prefab api example repository that shows how to customise the stage environment, but it does so by instantiating some objects into the stage. (For example, a floor plane)

    Here

    We want to load a specific scene as the stage.

    I know you can change the environment scene via the player settings, but we want to be able to load different scenes based on our own conditions.
     
  2. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    I found I can change the prefab regular environment variable to the scene I want before I open the prefab, like so:
    Code (CSharp):
    1. var prevEnvironment = EditorSettings.prefabRegularEnvironment;
    2. EditorSettings.prefabRegularEnvironment = desiredScene;
    3. AssetDatabase.OpenAsset(myPrefabToEdit);
    4. EditorSettings.prefabRegularEnvironment = prevEnvironment;
    Which works!

    I restore the users prefered prefab editing environment after I am done, so that it doesn't just keep opening up this random scene every time the user edits a prefab.

    This brings rise to a new problem...

    If the user edits a nested prefab inside the prefab stage, they will go into a new stage and the new stage will not use the 'desiredScene'. It'll use whatever the default one is. Then, when the user clicks 'back' to go back into editing the prefab, it does not re-load the 'desiredScene', instead it uses the default environment.

    Expected:
    [Edit PrefabA] -> [PrefabA open in 'DesiredScene'] -> [Edit nested PrefabB] -> [PrefabB open in 'default scene'] -> [Go Back] -> [PrefabA open in 'DesiredScene']

    Actual:
    [Edit PrefabA] -> [PrefabA open in 'DesiredScene'] -> [Edit nested PrefabB] -> [PrefabB open in 'default scene'] -> [Go Back] -> [PrefabA open in 'default scene']

    I understand why this is happening, but I don't know how to work around it. I need some way to add some logic that decides which scene should be open for some prefab.
     
  3. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    There doesn't appear to be any hooks in the code base for this kind of stuff. It's just hard coded to work with Unity's systems. Only 2 options - what Unity considers a 'UI' and what isn't considered a UI. Is there plans for this stuff to be fleshed out so that asset authors and project developers can create their own rules? :)

    https://github.com/Unity-Technologi.../StageManager/PrefabStage/PrefabStage.cs#L142
     
  4. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
  5. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Is there plans for it? I guess I could load the desired scene as a preview scene and move over all the root objects into the actual prefab stage scene? Does feel like a big hack though.
     
  6. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Yes, but not in the 18.x cycle
     
    Prodigga likes this.
  7. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    @SteenLund so, a hacky workaround I've worked out is:

    On 'My Edit Button' clicked:
    • Save prefabRegularEnvironment scene path to EditorPrefs
    • Replace prefabRegularEnvironment with desired scene
    • Open desired prefab for edit
    When user 'finished' their prefab editing session:
    • Restore prefabRegularEnvironment back to what it was
    So this has the effect of keeping the user in the desired scene the duration of their 'prefab editing session', while they are: 1) editing the prefab 2) editing nested prefabs 3) navigating 'back' using the hierarchy back button, out of a nested prefab, up until they 'leave' all stages and go back to editing the scene.

    The tricky part was trying part was detecting when the users 'prefab editing session' has ended. The only callback available is 'prefabStageClosing', which isn't good enough because GetCurrentPrefabStage will still return a stage, and also it seems like the stage closes and opens when navigating into a nested prefab and back out of a prefab. My solution was to just use DelayCall in the editor to delay my check by one frame. If the user stops editing their prefab and backs out into the scene view, then the next frame GetCurrentPrefabStage returns null. Once I detect this I can restore their prefabRegularEnvironment.

    This all seems to be working pretty well. Figured I would let you know how I went about it so you can get more of an idea of the kind of thing we were trying to achieve. :)
     
    Last edited: Mar 1, 2019
    SugoiDev likes this.