Search Unity

  1. All Pro and Enterprise subscribers: find helpful & inspiring creative, tech, and business know-how in the new Unity Success Hub. Sign in to stay up to date.
    Dismiss Notice
  2. Dismiss Notice

Help Wanted Create Prefabs via CreateAssetMenu inside Project view

Discussion in 'Prefabs' started by Noblauch, May 5, 2021.

  1. Noblauch

    Noblauch

    Joined:
    May 23, 2017
    Posts:
    248
    Hi, I want to create prefabs via the right click menu directly inside the project:
    CreateAssetMenu.png

    I know I can create prefabs inside the Hierarchy with:
    Code (CSharp):
    1. [MenuItem("GameObject/MyAssets/Prefab", false, TeasersPriority)]
    2. MyCreateFunction()
    But this only works inside the scene hierarchy.

    I know I can create Scriptable Objects with:
    Code (CSharp):
    1. [CreateAssetMenu(fileName = "Prefab", menuName = "MyAssets/Prefab")]
    2. public class MySO : ScriptableObject
    But I need a mixture of two. I need the CreateAssetMenu to spawn a prefab just like a scriptable object, direct in my project tree.
    How is it done?
     
  2. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    6,968
    Code (CSharp):
    1. [MenuItem("FooBar/Prefab")]
    2. private static void PrefabC() {
    3.     var assetPath = "Assets/MyTempPrefab.prefab";
    4.     var source = new GameObject("Root");
    5.     var childA = new GameObject("A");
    6.     childA.transform.parent = source.transform;
    7.     PrefabUtility.SaveAsPrefabAsset(source, assetPath);      
    8. }
    Adapted from here:
    https://docs.unity3d.com/ScriptReference/PrefabUtility.EditPrefabContentsScope.html
     
    Noblauch likes this.
  3. Noblauch

    Noblauch

    Joined:
    May 23, 2017
    Posts:
    248
    Okay, I gave MenuItem another shot, and fair enough, of course I could add it to the Create menu.
    The only thing you need to know is, that right clicking the project tab is the same as going to Assets over the top menu.

    So what I had to do was the following:
    Code (CSharp):
    1. [MenuItem("Assets/Create/MyPrefab")]
    2. CreatePrefabInProject("MyPrefab")
    Next problem was, from here I couldn't get the currently open folder path. I stumbled across a post to get it via reflection, so I added this for our utils class:
    Code (CSharp):
    1.         public static string CurrentProjectFolderPath
    2.         {
    3.             get
    4.             {
    5.                 Type projectWindowUtilType = typeof(ProjectWindowUtil);
    6.                 MethodInfo getActiveFolderPath = projectWindowUtilType.GetMethod("GetActiveFolderPath", BindingFlags.Static | BindingFlags.NonPublic);
    7.                 object obj = getActiveFolderPath.Invoke(null, new object[0]);
    8.                 return obj.ToString();
    9.             }
    10.         }
    Next up was to actually create a copy of the prefab template, which I did via the
    AssetDatabase.CopyAsset()
    function, since this seemed to be the most straight forward way:
    Code (CSharp):
    1.         private static void CreatePrefabInProject(string prefabName)
    2.         {
    3.             var prefab = UnityEngine.Resources.Load(prefabName);
    4.             string targetPath = $"{CurrentProjectFolderPath}/{prefabName}.prefab";
    5.             AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(prefab), targetPath);
    6.         }
    The template prefabs were therefor placed inside a Resource Folder like so:
    Resources/MyPrefab
     
unityunity