はじめに
気付いたきっかけ。
UnityEditor上では問題なく動くのに、Buildすると意図通りに動かない。そんな現象にあたりました。
MonoBehaviour(A)にBakerクラスを追加して、SpawnerComponentを作成。
別のMonoBehaviour(B)のStart()内で、SpawnerComponentにオブジェクトの生成数を設定。
SpawnerのSystemで設定された生成数分のオブジェクトをInstantiateということをやろうとしました。
しかし、これがUnityEditor上では動くのにビルドすると動かない状態になりました。
原因
最初原因がさっぱりわからなかったのですが、処理を追っていった結果、MonoBehaviour(B)のStart()内で、SpawnerComponentの取得に失敗しているようでした。
つまるところ、EditorとExeでのメソッドの実行順が変わってしまっていて、ExeではMonoBehaviour(A)のBakeメソッドが呼ばれる前にMonoBehaviour(B)のStartが呼ばれる挙動になっているようです。
対応
Bakeメソッドが呼ばれていること自体は確認できていて、順番だけの問題なので、Startメソッドでやりたかった処理内容をCoroutine化して、SpawnerComponentが生成されるまで繰り返すのが一番簡単そうな解決策でした。
実装例
MonoBehaviour(B)の初期化処理
void Start()
{
StartCoroutine(InitializeWithDelay());
}
private IEnumerator InitializeWithDelay()
{
while (World.DefaultGameObjectInjectionWorld == null)
{
Debug.Log("Waiting for World...");
yield return null;
}
_entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
_cubeQuery = _entityManager.CreateEntityQuery(ComponentType.ReadWrite<CubeControlInfo>());
while (true)
{
using var spawnerQuery = _entityManager.CreateEntityQuery(ComponentType.ReadWrite<EntitySpawnerComponent>());
if (!spawnerQuery.IsEmpty)
{
var entity = spawnerQuery.GetSingletonEntity();
var spawnerComponent = _entityManager.GetComponentData<EntitySpawnerComponent>(entity);
//spawnerComponentになんか設定する
spawnerComponent.settingA = A;
_entityManager.SetComponentData(entity, spawnerComponent);
Debug.Log("Successfully updated EntitySpawnerComponent");
break;
}
yield return null;
}
}
さいごに
Editor上とExeの挙動が異なると困りますよね。
WinFormsのReleaseビルドとDebugビルドで動きが違うとかも追うのが大変なので、めっちゃ困ります。
でも、しばしばあたる問題なので、ノウハウを蓄積していきたいと思う今日このごろ。
どなたかのお役に立てば幸いです。


コメント