Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Scriptable Objects Reorder Parent/Child when renamed

Discussion in 'Scripting' started by BusStopStudios, Dec 23, 2020.

  1. BusStopStudios

    BusStopStudios

    Joined:
    Mar 28, 2015
    Posts:
    22
    How I got here: I have been working on a tool that uses scriptable objects which have child scriptable objects. The system works really well, however when I rename the SO the parent/child relationship breaks in Unity.

    I have managed to get this down to a very simple case study now.

    Using the code below, you create a Container SO asset. Then using the MyMenu you create the Data which is a child to the Container. All this works as expected and the relationship in the Project is:

    Container -> Data

    However, once you rename the Container SO to something else, Unity reorders the Parent Child so that the Data is now the Parent and Container is the Child:

    Data -> Container

    Below is the code that should duplicate this issues (Unity 2020.1.17f1 - Also had same results on 2020.1.8)

    Container.cs
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [CreateAssetMenu]
    4. public class Container : ScriptableObject
    5. {
    6. }
    Data.cs
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Data : ScriptableObject
    4. {
    5. }
    CustomEditor.cs

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. public class CustomEditor : Editor
    5. {
    6.     [MenuItem("MyMenu/Create Data for Container")]
    7.     static void CreateDataForContainer()
    8.     {
    9.         Container container = Selection.activeObject as Container;
    10.         if (container != null)
    11.         {
    12.             Data data = ScriptableObject.CreateInstance(typeof(Data)) as Data;
    13.             data.name = data.GetType().Name;
    14.             if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(container)))
    15.             {
    16.                 AssetDatabase.AddObjectToAsset(data, container);
    17.             }
    18.             AssetDatabase.SaveAssets();
    19.         }
    20.     }
    21. }
    NOTES
    • At first I thought this was an issue with namespaces but not the case
    • Thought this could be an assembly issue but not the case now with basic classes
    • Close/Open project results are same
    • ASSET file is identical after rename
    If you experienced this I'd love to know what I'm doing wrong here, my tool is almost done and this is stopping me from pushing it out. Thanks!
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,517
    If a Container has references to Data, and Data has references to Container, I don't think Unity's serializer handles circular references. Are there any warnings in the console?

    If a Data does NOT have a reference to a Container, how is it referring to it in this reversed parent-child relationship you speak of?
     
  3. BusStopStudios

    BusStopStudios

    Joined:
    Mar 28, 2015
    Posts:
    22
    The code posted above is exactly what I have used to make a repo case. The Container does not have a reference to Data and Data does not have a reference to Container.

    My example is the Project View. Container is the Parent and Data is a sub-asset to Container. When it is renamed then Data becomes the parent asset and Container becomes the sub-asset. Below is the visual

    Using code above, I create the New Container.


    Now I rename it to be "New Container New Name" but as you can see asset has changed from Container to Data.


    What I don't understand is why xNode can do what I am doing but my case (which I have simplified) does not work. xNode works well and my code is basically the same.
     
  4. BusStopStudios

    BusStopStudios

    Joined:
    Mar 28, 2015
    Posts:
    22
  5. Kerihobo

    Kerihobo

    Joined:
    Jun 26, 2013
    Posts:
    65
    Tearing my hair out over this. Still an issue in 2020.1.17f1.

    I see a fix is on the way but for now... urgh...
     
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,915
    Well I think there are some things that should be cleared up. First of all if you store multiple assets into an asset file, there is no hierarchy, at all. An asset file is just a container similar to an archive file (zip, tar). In the past the asset that was "shown" as the "parent" in the project view was the first asset in the file. However even in the past there was a strange behaviour when you store some built-in assets along with your own custom scriptable objects. Usually the built-in asset took precedence. So if you had a scriptable object and you added a Mesh or Material to the file, that Mesh or Material became the root.

    Unity later added the method SetMainObject. Which you could use to specify which of the objects in an asset file should be the main object. Though I haven't really used it yet. It's still on my todo list. I always liked the concept of asset files to allow for example procedural geometry controlled by a scriptable object and the generated mesh being a sub asset.

    As for why the order changes / the main asset information is lost when you rename the file I have no idea. Maybe it gets preserved when you actually used SetMainObject? Otherwise the assets have more or less the same priority within the asset file.

    When text serialization is used you can open your asset file in a normal text editor to see the actual structure. Even scene files do not really have a hierarchical structure. It's only the transform components which build up a hierarchy. Inside the file the various objects and components could be all over the place in a long linear list.
     
  7. BusStopStudios

    BusStopStudios

    Joined:
    Mar 28, 2015
    Posts:
    22
    @Bunny83 I understand the file structure and its very simple to see how they make the references and which is the main object. Using scriptable objects as one like I am is very helpful when doing procedural stuff (which is what I am working towards). The file structure was not the problem and neither was the code. The issue was a bug on Unity's end, I can only assume there was a bug in the AssetDatabase itself and something was cached causing them to visually look different (but still be the same file).

    @Kerihobo The bug is fixed in Unity 2020.21f1 I am using this now and haven't seen any issues.
     
  8. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    533
    I have a similar problem with Unity 2019.4.1f1. Im not sure if there is a patch for this version, but I adjusted my editor script to call SetMainObject on my "parent" SO everytime after I add/remove a "child" SO from it, it seems to fix the rename problem for me, but I have no idea how because the actual file content looks identical (well obviously the name and ids are different) I don't see any additional information inside the file where the "main" object is flagged, maybe this information is stored somewhere else, but I guess it doesn't matter in the end as long as it works.

    I think the default sorting depends on the SO.name, I will try to add some extra code to add a number to all child objects so that they are stored in the "correct" order just to be extra sure.

    Edit: The "mainObjectFileID" seems to be stored in the .meta file, it's set to 0 for all SO that I created before I changed my editor script and now it's set to the correct id after calling SetMainObject.
     
    Last edited: Jan 11, 2021
  9. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,915
    Yep, there's most likely where they store this information. The main object is a pure editor feature since at runtime this doesn't really matter since you usually have setup direct serialized references to assets.