Search Unity

Editor Script - I cannot instantiate a prefab from a LoadPrefabContents

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

  1. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    I am writing a script that creates prefabs from a mesh that is split up into tiles. I have the mesh loading, splitting and saving as assets.

    The problem comes with prefabs. I want to:

    If there is a prefab, instantiate a bunch at various rotations.
    If there isn't, create the prefab with a link to its mesh.

    I have the "create" side working, although different to my explanation here because nested meshes cannot be edited after. It suits me to save them separately anyway.

    Code (CSharp):
    1.  
    2. private (GameObject prefab, GameObject instance) CreateAndSavePrefab(Tile tile, Mesh mesh)
    3.         {
    4.             var prefabGo = new GameObject($"{tile.Name}");
    5.             TileView tileView = prefabGo.AddComponent<TileView>();
    6.  
    7.             var meshFilter = prefabGo.AddComponent<MeshFilter>();
    8.             meshFilter.sharedMesh = tile.Mesh;
    9.  
    10.             MeshRenderer meshRenderer = prefabGo.AddComponent<MeshRenderer>();
    11.             meshRenderer.material = Material;
    12.  
    13.             prefabGo.gameObject.layer = gameObject.layer;
    14.  
    15.             var prefab = PrefabUtility.SaveAsPrefabAssetAndConnect(prefabGo, PrefabPathFromName(tile.Name), InteractionMode.AutomatedAction);
    16.             return (prefab, prefabGo);
    17. }
    The output of that goes into a dictionary, keyed by prefab.

    I can then loop through the keys of that dictionary and do:

    var newView = PrefabUtility.InstantiatePrefab(prefab) as GameObject;


    I need a "Load" way of doing the "SaveAsPrefabAssetAndConnect". I've tried:


    Code (CSharp):
    1. var prefab = PrefabUtility.LoadPrefabContents($"Assets/Resources/Tiles/{tile.Name}.prefab");
    2.                     var instance = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
    Prefab is loaded but instance is not. I don't understand. What am I doing wrong? I can't find any examples of this; the code in the API uses "Selection". Apologies for the tone, I have precious little spare time and what should be easy to do is eating it fast.

    Many thanks!
     
  2. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    I have a solution of sorts - although I don't know why this works and
    LoadPrefabContents
    doesn't.

    Code (CSharp):
    1. var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PrefabPathFromName(tile.Name));
    2. var instance = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
    Using this area of the API is really unsettling and confusing and that's coming from someone who used to code DCOM.
     
  3. Peter_Olsted

    Peter_Olsted

    Unity Technologies

    Joined:
    Apr 19, 2021
    Posts:
    75
    Hi there,
    I cannot comment on the names of the methods, but there is some hints in the documentation for PrefabUtility.LoadPrefabContents. It's not meant as a load an asset ready for use in a scene, but an util for editing a prefab without it being in the scene.

    'Loads a Prefab Asset at a given path into an isolated Scene and returns the root GameObject of the Prefab.
    You can use this to get the content of the Prefab and modify it directly instead of going through an instance of the Prefab. This is useful for batch operations.'


    You found the correct solution yourself with using LoadAssetAtPath.

    Let me know if there is anything else we can help with.