Save Unity.Object as an asset

Hi guys,

I am trying to use AssetDatabase.CreateAsset to save some custom made data (grid in this example). I know that in order to use CreateAsset, I need to pass an Unity.Object instance. So I create a specific class that inherits from Unity.Object and have just one field that holds my data.

public class GridSaveObject : UnityEngine.Object
{
    public GridMapData gridMapData;

    public GridSaveObject(GridMapData gridMapData)
    {
        this.gridMapData = gridMapData;
    }
}

Now, inside the custom inspector (in Editor mode only, but I don’t think that is the problem here), I make a call:

var obj = new GridSaveObject(new GridMapData());
Debug.Log(obj== null); // returns true

I don’t even see the reason to mention anything that goes after that, cause what’s the point. The question, how does one create an instance of such objects? I know it is possible, cause the unity way of creating Materials is the same
var mat = new Material (some_link_to_shader);

Unity Objects aren’t generally supposed to be inherited from directly and also have some weird quirks that you would be experiencing here. ‘Object == null’ doesn’t do what you are probably expecting - in order to guarantee safety with Unity’s object instancing systems, Unity overloads the ‘==’ operator for objects such that they do additional checks against the scene rather than just checking if the object pointer is valid. In the case of a GameObject this would work because the GameObject() constructor automatically adds it to the scene and initialises it, however because Object is just a generic base class that isn’t the case and therefore you would need to handle it manually. This exact use case is actually shown as an example in the docs at the bottom of the ‘Object.operator ==’ page;

ScriptableObject inherits from UnityEngine.Object and is designed pretty specifically for this case; serializing an object to a Unity asset. ScriptableObjects should be created via the CreateInstance method, so I’ve added a static function to work in the same way your constructor would above.

[System.Serializable]
public class GridSaveObject : ScriptableObject
{
    public GridMapData gridMapData;
 
    public static GridSaveObject NewInstance(GridMapData gridMapData)
    {
        GridSaveObject instance = ScriptableObject.CreateInstance<GridSaveObject>();
        instance.gridMapData = gridMapData;
        return instance;
    }
}

...

GridSaveObject obj = GridSaveObject.NewInstance (new GridMapData ());
AssetDatabase.CreateAsset (obj, "GridObject.asset");

I would also make sure to mark your GridMapData class as [Serializable] if you want it to work properly with the Unity Editor/serializer.