2015年10月17日土曜日

オブジェクトのタグ名検索でハマったこと

Unityでオブジェクトのタグ名検索でちょっとハマったのでメモ。

結論からいうと、オブジェクトのタグ名検索があてにならない特定の状況&タイミング(?)があるので注意。
※ひょっとするとどこかに明記されてる(?)既知の仕様かもしれません。


■環境


Unity 5.1.1f1 personal (C#使用)
Windows7


■注意すべき状況&タイミングの概要


タグ付け済みの子オブジェクトを含む親オブジェクトのプレハブがあるとします。
そして既にシーン上にInitiate済みとします。

説明の便宜上オブジェクト名、タグ名は以下とします。
  • 親オブジェクト名:ObjectA
  • 子オブジェクト名:ObjectC (タグ名:TagObjectC)


問題(?)が起きる手順。
  1. タグ名(TagObjectC)で検索したものを GameObject型の変数に保存。
    ※特に問題なし。
     
  2. ※時間経過でフレームが進み、現在 n フレームとします。
     
  3. ObjectA を Destroyする。
    ※つまり子オブジェクト(ObjectC)も消えます。
     
  4. 同フレーム中にObjectAを再度Initiateする。
     
  5. 「1.」でタグ名(TagObjectC)検索&保存済みのGameObject型の変数の指すObjectCは既にDestroy済み。
    新たにタグ名(TagObjectC)で検索して保存しなおします。
    つまり「4.」で Initiate した ObjectA 内にて検索&結果が返ることを期待しています。
     
  6. ※時間経過で次のフレームに進み、現在 n+1フレームとします。
     
  7. 前フレームでタグ名検索&保存しておいた GameObject型の変数にて ObjectCを参照してみます。
    この時、この変数 はいつのまにか勝手に null になっています。

ちょっとややこしいですが(;・∀・)

注意する点の要約は、

  1. 同フレーム中に同名のプレハブをシーン上でDestroy &  Initiate した。
    ※シーン中に当該プレハブの同時存在は1つ。
     
  2. さらに同フレーム中にてタグ名検索をかけた。
    ※新たにInitiateしたプレハブのオブジェクト内で検索HIT&結果取得することを期待。
     
  3. Destroyした方のタグの付いたオブジェクトを返している&同フレーム中は null ではない。
     
  4. 次のフレームでいつのまにか null になっているので「アレっ?」となる。
    ※Destroy処理がタグ名の内部DB?Hash?にも反映された為?


多分、同フレーム中での実際のオブジェクトのDestroyの処理が行われるタイミング、タグ名とシーン上のオブジェクトの関連性更新などのタイミングの差異問題だと思うので「そういう仕様になっている」ような気がします。

※上記処理の確認はUpdate()内で行っています。FixedUpdate内では未確認。こっちだとひょっとするとDestroy後タグ名の参照先更新(?)がされるかも?


■回避策


今回の状況&タイミングにおいては、子オブジェクト名で検索をするように実装すれば回避できています。
つまりオブジェクト名検索ではさすがに同フレーム中でもInitiateした最新の方をみてくれるようです。

なので今回のケースではタグ名検索を使わなければハマらなかったわけですが(汗。

前々からタグ名検索は便利そうな反面「何かありそう」なモヤっとした雰囲気を感じていたのが少し納得できた感じです。



0 件のコメント:

コメントを投稿