Search Unity

SaveAsPrefabAssetAndConnect breaking references to prefab.

Discussion in 'Prefabs' started by xshadowmintx, Mar 17, 2021.

  1. xshadowmintx

    xshadowmintx

    Joined:
    Nov 4, 2016
    Posts:
    47
    I've spent so long reading the threads about how to edit prefabs, I'm so over it.

    What is the difference between SaveAsPrefabAsset and SaveAsPrefabAssetAndConnect?

    The docs are so vague:

    < Use this function to create a Prefab Asset at the given path from the given GameObject including any children in the Scene and at the same time make the given GameObject into an instance of the new Prefab.
    ---
    > Use this function to create a Prefab Asset at the given path from the given GameObject, including any childen in the Scene without modifying the input objects.

    What does that even mean? An instance of the new prefab like a new object when you're saving a prefab? How is that ever the right thing to do, and why does everyone seem to recommend using it?

    ...using SaveAsPrefabAssetAndConnect (despite being the recommended approach by most threads here) appears to be totally broken.

    In detail, in my case:

    I have this:

    prefabA has a 'StoryDialog' component on it.
    prefabB has a List<StoryDialog> on it.

    prefabB references prefabA:

    out1.png

    I use an editor script to modify prefabA, and I get:

    out2.png

    What.

    Let's have a look at what happens when you save the prefab using git:

    Code (CSharp):
    1. diff --git a/Assets/Story/Chapter1/Dialog/Dialog.Mancy.prefab b/Assets/Story/Chapter1/Dialog/Dialog.Mancy.prefab
    2. index e2ad264..408de7f 100644
    3. --- a/Assets/Story/Chapter1/Dialog/Dialog.Mancy.prefab
    4. +++ b/Assets/Story/Chapter1/Dialog/Dialog.Mancy.prefab
    5. @@ -1,6 +1,6 @@
    6. %YAML 1.1
    7. %TAG !u! tag:unity3d.com,2011:
    8. ---- !u!1 &8212909838568895111
    9. +--- !u!1 &1772136667278650187
    10. GameObject:
    11.    m_ObjectHideFlags: 0
    12.    m_CorrespondingSourceObject: {fileID: 0}
    13. @@ -8,8 +8,8 @@ GameObject:
    14.    m_PrefabAsset: {fileID: 0}
    15.    serializedVersion: 6
    16.    m_Component:
    17. -  - component: {fileID: 7150374724305374130}
    18. -  - component: {fileID: 1453186552420189131}
    19. +  - component: {fileID: 744997186491929214}
    20. +  - component: {fileID: 9027246011504024071}
    21.    m_Layer: 0
    22.    m_Name: Dialog.Mancy
    23.    m_TagString: Untagged
    24. @@ -17,13 +17,13 @@ GameObject:
    25.    m_NavMeshLayer: 0
    26.    m_StaticEditorFlags: 0
    27.    m_IsActive: 1
    28. ---- !u!4 &7150374724305374130
    29. +--- !u!4 &744997186491929214
    30. Transform:
    31.    m_ObjectHideFlags: 0
    32.    m_CorrespondingSourceObject: {fileID: 0}
    33.    m_PrefabInstance: {fileID: 0}
    34.    m_PrefabAsset: {fileID: 0}
    35. -  m_GameObject: {fileID: 8212909838568895111}
    36. +  m_GameObject: {fileID: 1772136667278650187}
    37.    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    38.    m_LocalPosition: {x: 0, y: 0, z: 0}
    39.    m_LocalScale: {x: 1, y: 1, z: 1}
    40. @@ -31,13 +31,13 @@ Transform:
    41.    m_Father: {fileID: 0}
    42.    m_RootOrder: 0
    43.    m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
    44. ---- !u!114 &1453186552420189131
    45. +--- !u!114 &9027246011504024071
    46. MonoBehaviour:
    47.    m_ObjectHideFlags: 0
    48.    m_CorrespondingSourceObject: {fileID: 0}
    49.    m_PrefabInstance: {fileID: 0}
    50.    m_PrefabAsset: {fileID: 0}
    51. -  m_GameObject: {fileID: 8212909838568895111}
    52. +  m_GameObject: {fileID: 1772136667278650187}
    53.    m_Enabled: 1
    54.    m_EditorHideFlags: 0
    55.    m_Script: {fileID: 11500000, guid: 4b2f4c66f4f7a4ff3b956a8abb792455, type: 3}
    It literally appears to be generating a new instance. That isn't what I want.

    Here's the entire code being used: https://gist.github.com/shadowmint/5417cdf37dc947e8ae862d54527127a4

    You'll see basically I load the prefab using:

    PrefabUtility.LoadPrefabContents(physicalPath);

    And save it using:

    PrefabUtility.SaveAsPrefabAssetAndConnect(prefabRef.root, assetPath, InteractionMode.AutomatedAction);

    However, it works correctly when calling:

    PrefabUtility.SaveAsPrefabAssetAndConnect(prefabRef.root, assetPath);

    Why?

    What is the practical use-case for SaveAsPrefabAssetAndConnect?

    Why would you ever edit a prefab and then save it at the same location as new object in a way that breaks all your prefab references?