Who resets member variables after Awake() has been called?

I have a MonoBehaviour that has an ExecuteInEditor attribute. When I run the game from editor, it crashes deterministically on OnEnabled() because all the data members are in their uninitialized state. I have a following test script that replicates this issue:

using UnityEngine;
using System.Collections.Generic;

[ExecuteInEditMode]
public class ExecuteInEditorTest : MonoBehaviour
{
	List<string> callHistory = new List<string>();
	System.Object testMember = null;
	
	void Awake()
	{
		callHistory.Add("Awake");
		testMember = new System.Object();
	}
	
	void Start()
	{
		callHistory.Add("Start");	
	}
	
	void OnDestroy()
	{
		callHistory.Add("OnDestroy");	
	}
	
	void OnEnable()
	{
		callHistory.Add("OnEnable");
		if (testMember == null)
		{
			foreach (string call in callHistory)
			{
				Debug.Log(call);	
			}
		}
	}
	
	void OnDisable()
	{
		callHistory.Add("OnDisable");	
	}
}

When I run a test scene from editor, the script logs

Awake
OnEnable
Start
OnEnable

or

Awake
OnEnable
OnEnable

Any idea who sets the testMember to null and when? And why the call history is not always the same?

The test scene has just one empty game object with this MonoBehaviour and the default camera.

Cheers,

Antti

This is an example of a great question. You've distilled the problem down to its core, provided code to recreate it, and showed that you worked yourself to try to figure it out. Nicely done.

1 Answer

1

Scripts in edit mode need to be able to survive Unity serializing them and recreating them. I’m not sure under which scenarios that happens, but it is quite often - starting and ending play mode is one scenario.

The Unity blog has a recent post that describes this sort of thing in detail, and how to do it right.

Thanks, that helped me to fix the issue on my test scene. I seems that OnEnable() must be able to initialize the object properly to make Unity's serialization work: void OnEnable() { if (testMember == null) { testMember = new System.Object(); } } I have to admit that I still don't fully understand why Unity serializes data from object who's Awake() hasn't been called. I'm assuming that happens here, at least that would explain the symptoms.