Long-Slow-Distance

Programming Notes with Unity

メニュー

指定したオブジェクトの子オブジェクトを全て削除する

特定のゲームオブジェクトを親として持つような管理をすることがよくあるのだが、
その際に「子オブジェクトを全て削除したい」というケースがよく発生する。

それらの子オブジェクトをシステムで管理していれば、そこから消すようにするのが妥当だが
全て管理するのも面倒であり、必要のない時もある。

そこでとりあえずサクッと消せるように以下のように汎用化したものを作成して使っている。

	//--------------------------------------------------------------------------------
	// 指定したオブジェクトにぶら下がってる子オブジェクトを全削除
	//--------------------------------------------------------------------------------
	public static void		DestroyChildObject( Transform parent_trans )
	{
		for( int i=0; i < parent_trans.childCount; ++i ){
			GameObject.Destroy( parent_trans.GetChild( i ).gameObject );
		}
	}

TransformクラスにあるchildCountで子の数、GetChildで子のTransformを取得出来る。

注意点というか仕様として、ゲームオブジェクトのDestroyは呼び出した時点では完全に削除されない。
実際に削除されるのはおそらく呼び出したフレームの最後のほうか、次のフレームのド頭だと思われる。
(ゲームオブジェクトはUnityのシステムで管理されており、Destroyは「あなたは削除フローに入ってね」という指令のようなもので削除準備をしているにすぎない)

呼び出した時点で完全に削除したい場合は、DestroyImmediateというメソッドがあり
これを扱う場合は以下のようにfor文での参照の仕方を変えて使用する。

	//--------------------------------------------------------------------------------
	// Immediate版 即時に消えるのでリストの参照の仕方が異なる
	//--------------------------------------------------------------------------------
	public static void		DestroyImmediateChildObject( Transform parent_trans )
	{
		for( int i = parent_trans.childCount - 1; i >= 0; --i ){
			GameObject.DestroyImmediate( parent_trans.GetChild( i ).gameObject );
		}
	}

GetChildに渡すインデックスを必ず子の最初か最後に固定すると、参照に問題が発生しなくなる。
基本的に配列やListは列挙中の削除に気をつける必要がある。

参考:
http://www.atmarkit.co.jp/fdotnet/dotnettips/815listremove/listremove.html
http://answers.unity3d.com/questions/678069/destroyimmediate-on-children-not-working-correctly.html

関連記事