Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved Create Scriptable Object in Asset when another one created

Discussion in 'Scripting' started by Toonas, Apr 11, 2021.

  1. Toonas

    Toonas

    Joined:
    Sep 4, 2017
    Posts:
    19
    Hi everyone!
    I have a problem. I have Scriptable Object class that initializing from CreateAssetMenu. This class needs to create another Scriptable Objects on initializing and add this objects to main Scriptable Object Asset.

    Code (CSharp):
    1. public class DialogController : ScriptableObject, ISerializationCallbackReceiver
    2. {
    3.     [SerializeField]
    4.     private StartNode m_StartNode;
    5.  
    6.     public void Initialize()
    7.     {
    8.         if (m_StartNode == null)
    9.         {
    10.             m_StartNode = CreateInstance<StartNode>();
    11.             m_StartNode.parentController = this;
    12.             m_StartNode.Name = "Start";
    13.  
    14.             AddObjectToAsset(m_StartNode);
    15.         }
    16.     }
    17.  
    18.     private void AddObjectToAsset(UnityEngine.Object obj)
    19.     {
    20.         //todo Doesn't work because main SO is not have asset yet!
    21.         if (AssetDatabase.Contains(this) && !AssetDatabase.Contains(obj))
    22.         {
    23.             AssetDatabase.AddObjectToAsset(obj, this);
    24.             AssetDatabase.SaveAssets();
    25.         }
    26.     }
    27. }
    I call Initialize() in OnGUI() in the editor (because don't know hot to do this another way). This code worked when it was in not package folder. But now it in package folder.

    I tried adding Scriptable Object OnBeforeSerialize().
    Code (CSharp):
    1. public void OnBeforeSerialize()
    2. {
    3.     AddObjectToAsset(m_StartNode);
    4. }
    But it didn't work.

    upload_2021-4-11_22-55-22.png

    So, I don't know how to create additional Scriptable Object with creating main Scriptable Object in Asset.
     
  2. Toonas

    Toonas

    Joined:
    Sep 4, 2017
    Posts:
    19
    I solved my problem. To initialize Scriptable Objects on creating assets can be used MenuItem attribute instead of CreateAssetMenu attribute. There is my example.
    Code (CSharp):
    1. [MenuItem("Assets/Create/Custom/Dialog/Dialog Controller")]
    2. public static void CreateAsset()
    3. {
    4.     var instance = CreateInstance<DialogController>();
    5.  
    6.     var selectionPath = AssetDatabase.GetAssetPath(Selection.activeObject);
    7.     var resultDirectory = Directory.Exists(selectionPath) ? selectionPath : Path.GetDirectoryName(selectionPath).Replace("\\", "/");
    8.  
    9.     var assetName = "DialogController";
    10.     var assetExtension = ".asset";
    11.     var resultPath = resultDirectory + "/" + assetName + assetExtension;
    12.  
    13.     for (int i = 1; File.Exists(resultPath); i++)
    14.         resultPath = resultDirectory + "/" + assetName + " " + i + assetExtension;
    15.  
    16.     AssetDatabase.CreateAsset(instance, resultPath);
    17.  
    18.     var startNode = CreateInstance<DialogNode>();
    19.     startNode.parentController = instance;
    20.     instance.m_DialogNodes.Add(startNode);
    21.  
    22.     startNode.Name = "Start";
    23.     startNode.Position = new Vector3(100, 200);
    24.     instance.StartNode = startNode;
    25.  
    26.     instance.AddObjectToAsset(startNode);
    27. }
    ItemName needs to be started with "Assets/Create" if you want to have your MenuItem in context menu in Project window.
    Source of solution: https://answers.unity.com/questions/1350054/createassetmenu-attribute-multiple-sub-menu.html