Search Unity

Creating prefabs programmatically, confused about GameObject return values

Discussion in 'Prefabs' started by brainwipe, Nov 11, 2021.

  1. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    When creating prefabs programmatically, I am confused about the difference between the
    GameObject
    prefab instance in the scene and whatever it is that gets returned from
    SaveAsPrefabAssetAndConnect
    . Let me explain...

    I have a prefab that's created like so:
    Code (CSharp):
    1. private GameObject CreatePrefab(Mesh mesh, Material material, string path)
    2. {
    3.   var prefab= new GameObject("test");
    4.  
    5.   var meshFilter = prefab.AddComponent<MeshFilter>();
    6.   meshFilter.sharedMesh = mesh;
    7.  
    8.   var meshRenderer = prefab.AddComponent<MeshRenderer>();
    9.   meshRenderer.material = material;
    10.  
    11.   var savedPrefab = PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, path, InteractionMode.AutomatedAction);
    12.  
    13.   AssetDatabase.AddObjectToAsset(mesh, savedPrefab);
    14.   var meshFilter = savedPrefab.GetComponent<MeshFilter>();
    15.  
    16.   meshFilter.sharedMesh = mesh;
    17.   PrefabUtility.SavePrefabAsset(savedPrefab);
    18.   return prefab;
    19. }
    The mesh is built procedurally in a design-time scene that's solely for building prefabs. I believe that I need to save the prefab before adding the mesh to the prefab as a child with
    AddObjectToAsset()
    . I've reached that conclusion using process of elimination. Is that right?

    With the prefab that is returned from this function, I can do instance things like:

    Code (CSharp):
    1. var prefab = CreatePrefab(...);
    2. prefab.transform.position = new Vector3(100,100,100);
    or, if I don't want to keep the instance...

    Code (CSharp):
    1. DestroyImmediate(prefab);
    However, where the confusion is that I would expect
    savedPrefab
    to have a type other than
    GameObject
    because if I were to return
    savedPrefab
    , then my
    transform.position
    or
    DestroyImmediate
    fails.

    What's the difference between the prefab instance and whatever is returned from
    SaveAsPrefabAssetAndConnect
    ?

    Many thanks, I'm truly trying to get a firm understanding of programmatic prefabs so that I can avoid issues when my tooling becomes more complex.

    P.S. I've read through but not entirely understood these threads:
    https://forum.unity.com/threads/how-do-i-edit-prefabs-from-scripts.685711/
    https://forum.unity.com/threads/cus...s-how-to-setup-overrides.675310/#post-4574266
     
  2. Peter_Olsted

    Peter_Olsted

    Unity Technologies

    Joined:
    Apr 19, 2021
    Posts:
    75
    That is lot of questions, let's try and break it down.
    First up, every Prefab (Asset) and Prefab Instance is a GameObject, but they don't behave in exactly the same way.
    With SaveAsPrefabAssetAndConnect you are converting a plain GameObject in your scene to both a Prefab Instance and a Prefab asset. The function returns a GameObject asset and the input parameter is converted into a Prefab Instance, which is just a GameObject that has a connection to its corresponding asset. You called this parameter 'prefab' (line 3).

    You can use AddObjectToAsset if you want to have the mesh as a sub-asset of the prefab, so what you are doing is correct.

    If you want to delete a Prefab Asset you need to use AssetDatabase.DeleteAsset, be aware that any Prefab Instance will loose its connection as its asset is deleted.

    I hope I covered everything, if I missed something please let me know.
     
    Last edited: Nov 12, 2021
    brainwipe likes this.
  3. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    You have covered everything wonderfully, thank you Peter!

    I'm glad I'm not barking up the wrong tree!
     
    Peter_Olsted likes this.