Month: May 2015

If you’ve worked with custom editor windows in Unity, you may have noticed that references to objects, such as GameObjects and ScriptableObjects, are lost when you hit the Play button. This is because Unity serializes your objects before entering playmode, creates new objects, and deserializes them. (See Unity’s blog post, Serialization in Unity, for more details.)

Public fields, or private fields marked as serializable, will retain their values in playmode:

public class MyEditorWindow : EditorWindow
{

    [SerializeField]
    private int myInt;

    [SerializeField]
    private MyScriptableObjectType myAsset;
...

Primitive values such as the myInt will be fine. But myAsset will be a reference to the pre-playmode asset, not the newly created and deserialized playmode version of the asset.

To retain a reference, record its instance ID using Object.GetInstanceID():

    [SerializeField]
    private int myAssetInstanceID;

    // Record the instance ID at some point, such as when you assign the reference:
    myAsset = foo;
    myAssetInstanceID = myAsset.GetInstanceID();

When you enter playmode, use EditorUtility.InstanceIDToObject():

myAsset = EditorUtility.InstanceIDToObject(myAssetInstanceID) as MyScriptableObjectType;

You can detect playmode by registering a method with EditorApplication.playModeStateChanged:

void OnEnable()
{
    EditorApplication.playmodeStateChanged += OnPlaymodeStateChanged;
}

void OnDisable()
{
    EditorApplication.playmodeStateChanged -= OnPlaymodeStateChanged;
}

void OnPlaymodeStateChanged() 
{
    if (EditorApplication.isPlaying) 
    {
        myAsset = EditorUtility.InstanceIDToObject(myAssetInstanceID) as MyScriptableObjectType;
    }
}

 

Month: May 2015

The Pixel Crushers forum will be down for a few days while we convert from bbPress to phpBB. In the meantime, please feel free to post on the Unity forum threads for the Dialogue System or Love/Hate, or use the contact form!