プレイボタンをポチっと押してから、実際にプレイ開始されるまでの間に呼ばれるコールバックの呼び出し順を調べてみたのでその覚書。
今回調べたもの
UnityEditor
- InitializeOnLoadAttribute
- InitializeOnLoadMethodAttribute
- EditorApplication.playModeStateChanged (Unity2017.2以降)
- EditorApplication.playmodeStateChanged (Unity2017.1以前)
- DidReloadScripts
- InitializeOnEnterPlayModeAttribute (Unity 2019.3以降)
UnityEngine
- RuntimeInitializeOnLoadMethodAttribute
- RuntimeInitializeLoadType
- AfterAssembliesLoaded (Unity2019.1以降)
- BeforeSplashScreen (Unity2019.1以降)
- SubsystemRegistration (Unity2019.2以降)
- RuntimeInitializeLoadType
- ISerializationCallbackReceiver
スクリプト
スクリプトはこちら
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// staticコールバックをテストする場合に定義する | |
#define TEST_STATIC_CALLBACK | |
using UnityEngine; | |
using System.Collections; | |
#if UNITY_EDITOR && TEST_STATIC_CALLBACK | |
using UnityEditor; | |
using UnityEditor.Callbacks; | |
[InitializeOnLoad] | |
static class TestInitializeOnLoad | |
{ | |
private static int _InitializeOnLoadMethodCount = 0; | |
static TestInitializeOnLoad() | |
{ | |
Debug.Log("TestInitializeOnLoad : " + _InitializeOnLoadMethodCount); | |
_InitializeOnLoadMethodCount++; | |
} | |
} | |
static class TestCallbackEditor | |
{ | |
private static int _InitializeOnLoadMethodCount = 0; | |
[InitializeOnLoadMethod] | |
static void InitializeOnLoadMethod() | |
{ | |
Debug.Log("TestCallbackEditor InitializeOnLoadMethod() : " + _InitializeOnLoadMethodCount); | |
_InitializeOnLoadMethodCount++; | |
#if UNITY_2017_2_OR_NEWER | |
EditorApplication.playModeStateChanged += PlayModeStateChanged; | |
#else | |
EditorApplication.playmodeStateChanged += PlayModeStateChanged; | |
#endif | |
} | |
#if UNITY_2017_2_OR_NEWER | |
static void PlayModeStateChanged(PlayModeStateChange state) | |
{ | |
Debug.Log("PlayModeStateChanged " + state + " : isPlayingOrWillChangePlaymode = " + EditorApplication.isPlayingOrWillChangePlaymode + " , isPlaying = " + EditorApplication.isPlaying); | |
} | |
#else | |
static void PlayModeStateChanged() | |
{ | |
Debug.Log("PlayModeStateChanged : isPlayingOrWillChangePlaymode = " + EditorApplication.isPlayingOrWillChangePlaymode + " , isPlaying = " + EditorApplication.isPlaying); | |
} | |
#endif | |
private static int _DidReloadScriptsCount = 0; | |
[DidReloadScripts] | |
static void DidReloadScripts() | |
{ | |
Debug.Log("TestCallbackEditor DidReloadScripts() : " + _DidReloadScriptsCount); | |
_DidReloadScriptsCount++; | |
} | |
#if UNITY_2019_3_OR_NEWER | |
private static int _InitializeOnEnterPlayModeCount = 0; | |
[InitializeOnEnterPlayMode] | |
static void InitializeOnEnterPlayMode() | |
{ | |
Debug.Log("TestCallbackEditor InitializeOnEnterPlayMode() : " + _InitializeOnEnterPlayModeCount); | |
_InitializeOnEnterPlayModeCount++; | |
} | |
#endif | |
private static int _RuntimeInitializeOnLoadMethodCount = 0; | |
[RuntimeInitializeOnLoadMethod] | |
static void RuntimeInitializeOnLoadMethod() | |
{ | |
Debug.Log("TestCallbackEditor RuntimeInitializeOnLoadMethod() : " + _RuntimeInitializeOnLoadMethodCount); | |
_RuntimeInitializeOnLoadMethodCount++; | |
} | |
} | |
#endif | |
public class TestCallbackBehaviour : MonoBehaviour, ISerializationCallbackReceiver | |
{ | |
#if TEST_STATIC_CALLBACK | |
private static int _RuntimeInitializeOnLoadMethodCount = 0; | |
[RuntimeInitializeOnLoadMethod] | |
static void RuntimeInitializeOnLoadMethod() | |
{ | |
Debug.Log("TestCallbackBehaviour RuntimeInitializeOnLoadMethod() : " + _RuntimeInitializeOnLoadMethodCount); | |
_RuntimeInitializeOnLoadMethodCount++; | |
} | |
private static int _AfterSceneLoadCount = 0; | |
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] | |
static void AfterSceneLoad() | |
{ | |
Debug.Log("TestCallbackBehaviour AfterSceneLoad() : " + _AfterSceneLoadCount); | |
_AfterSceneLoadCount++; | |
} | |
private static int _BeforeSceneLoadCount = 0; | |
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] | |
static void BeforeSceneLoad() | |
{ | |
Debug.Log("TestCallbackBehaviour BeforeSceneLoad() : " + _BeforeSceneLoadCount); | |
_BeforeSceneLoadCount++; | |
} | |
#if UNITY_2019_1_OR_NEWER | |
private static int _AfterAssembliesLoadedCount = 0; | |
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)] | |
static void AfterAssembliesLoaded() | |
{ | |
Debug.Log("TestCallbackBehaviour AfterAssembliesLoaded() : " + _AfterAssembliesLoadedCount); | |
_AfterAssembliesLoadedCount++; | |
} | |
private static int _BeforeSplashScreenCount = 0; | |
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)] | |
static void BeforeSplashScreen() | |
{ | |
Debug.Log("TestCallbackBehaviour BeforeSplashScreen() : " + _BeforeSplashScreenCount); | |
_BeforeSplashScreenCount++; | |
} | |
#endif | |
#if UNITY_2019_2_OR_NEWER | |
private static int _SubsystemRegistrationCount = 0; | |
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] | |
static void SubsystemRegistration() | |
{ | |
Debug.Log("TestCallbackBehaviour SubsystemRegistration() : " + _SubsystemRegistrationCount); | |
_SubsystemRegistrationCount++; | |
} | |
#endif | |
#endif | |
private int _AfterDeserializeCount = 0; | |
void ISerializationCallbackReceiver.OnAfterDeserialize() | |
{ | |
Debug.Log("TestCallbackBehaviour OnAfterDeserialize() : " + _AfterDeserializeCount); | |
_AfterDeserializeCount++; | |
} | |
//private int _BeforeSerializeCount = 0; | |
void ISerializationCallbackReceiver.OnBeforeSerialize() | |
{ | |
//Debug.Log("TestCallbackBehaviour OnBeforeSerialize() : " + _BeforeSerializeCount); | |
//_BeforeSerializeCount++; | |
} | |
} |
これを適当なGameObjectに張り付けて、プレイボタンをポチっとすればConsoleにログが表示されます。
Unity2020.1.2f1で確認
試しにUnity2020.1.2f1で確認してみたところ以下のようになりました。
※ Enter Play Mode Settingsはオフ(全てリロードされる状態)
※「PlayStart」、「 Play : 時間」と出るログは別物のログ。
※「Error detecting ~」はVS周りのエラーログ(?)
個人的にOnAfterDeserialize()が呼び出されるタイミングが意外ですね。
- プレイボタン押した直後からInitializeOnEnterModeの間に古いインスタンスのOnAfterDeserializeが呼ばれている点
- DidReloadScripts直後に呼ばれておりBeforeSceneLoad~AfterSceneLoadの間ではない点
この辺りは気を付けたほうが良さそうです。
Unityのアセット販売中!
ステートマシンの状態遷移やパラメータはエディタで編集でき、
ゲームロジックに依存するステートの挙動はスクリプトで記述可能なエディタ拡張。
RPGツクールVXやWOLF RPGエディターのオートタイルに準拠したエディタ拡張。