Editing scripts while running in the editor?

Hi all,

I’ve noticed that you can actually edit your scripts while the game is running in the editor, and changes you make to the script generally update while it’s still running.

However some things don’t really like this, such as Dictionaries which seem to get emptied, or removed or something whenever you change a script, so you have to stop the game and restart it.

Is there a reason for this, or any way around it?

Thanks

edit: Is it because Dictionaries are not serializable? If so, is there any workaround? Does it also effect HashTables?

Wow, how is there no reply to this thread? This is a really good question. I did just run across a reference to the fact that Dictionaries aren’t serializable while researching this… does anyone know if this is the cause? And whether this will be getting changed?

I love this “edit and keep playing” functionality and I hate that it breaks down as soon as I start depending on a Dictionary.

Lack of serialisation support could well be the issue, though I haven’t investigated to confirm.

I’m not sure what goes on when a script gets re-compiled and re-loaded when in Editor playback, but I would guess that the existing object has to be destroyed and replaced with a new instance of the updated class. It’s quite possible that Unity is unable to automagically handle non-serialisable data when this happens.

I can provide a lot of details, but not a definitive answer as I haven’t succeeded in making this work as well as I’d like to.

The best reference I know is here:

There are also some useful hints in Richard Fine’s talk at the London Unity User Group’s 11th meeting - video here:

http://blogs.unity3d.com/2012/04/27/london-unity-usergroup-11/

So I’ve never had much success with this - it doesn’t behave how the documentation suggests. For example, private int fields seem to get serialized, but I haven’t had any success getting a custom type derived from UnityEngine.Object to serialize, whether the field is public or private, and regardless of use of the SerializeField attribute or the Serializable attribute. The reference just goes null. The inability to create my own serializable objects is the biggest barrier to this system being useful to me.

Overall you can still benefit from the runtime code updates if you’re careful, but you need to be able to reconstruct all unserializable data from serialized data and scene state, when it happens. The only method call you receive in this event is OnEnable - note that you also receive it in other circumstances. But you can design your class to have a set of serializable fields, and a set of unserializable fields whose values are derived from the serializable data and aspects of the scene (e.g. cached lookups of other components on the object, scene scans to find related GameObjects, etc).

When your component is initially created, on startup or as a result of loading a scene, or instantiating a prefab, the serializable fields will all be filled in but the unserializable data will be blank (zero, null, etc). Detect this state in OnEnable (not Awake or Start) and initialize the unserializable fields. Later calls to OnEnable don’t need to recreate all this data, in general, so you can avoid some overhead by checking an arbitrary field against null before repopulating everything.

So long as important persistent data is only stored in the serializable fields, this will also support code reloading, as Unity will serialize your state, unload and reload your assembly, and deserialize your state again - and all your components will get OnEnable called.

This doesn’t work for unserializable data that stores important variable game state - you need to avoid that. Note that lists of serializable types are serializable, but dictionaries are not - there’s only a small set of types which Unity blesses. If you could create your own objects that serialize correctly then this problem would go away, but as I said before, I didn’t have any success with that when I tried it, and no longer trust the documentation about it. So for now the best workaround I know of is to store the core data in serializable types and provide your own IDictionary wrapper around the raw data.

All in all it’s disappointing, and almost impossible to use properly. Maybe somebody else knows why I can’t create custom Unity-serializable types though - it would be great to know, as that’s the biggest stumbling block for me here.

The other big problem I’ve found with this is that coroutines get lost, and it’s pretty much impossible to resurrect them, unless they’re very basic.

Maybe because you are derriving from UnityEngine.Object which is the base class for alle UnityEngine classes but does not replace System.Object which is the base of EVERY class (even UnityEngine.Object).

Here an example:

using System;
using UnityEngine;

public class MyClass : MonoBehaviour
{
    [SerializeField]
    private MyDataClass data;

    protected virtual void Start()
    {
        data.name = "Steve";
    }

    protected virtual void OnEnable()
    {
        Debug.Log( data.name, this );
    }
}

[Serializable]
public class MyDataClass
{
    public string name;
}

This is just explanatory, but should work nevertheless (havn’t tested)

I see, you’re right - SerializableAttribute works on everything except classes derived from UnityEngine.Object. Kind of the opposite to what it says in the documentation. The only reason I was deriving from UnityEngine.Object was because the documentation told me to.