前提・実現したいこと
子オブジェクトの一括削除を調べていて、こちらのサイトを見たのですが、
C#
1 go.transform.Cast<Transform>().ToList().ForEach(x => { x.parent = null; GameObject.Destroy(x.gameObject);}
このコードのCast<Transform>()って何をしているかご教示いただけませんか?
試したこと
キャストが型変換なのはわかっています。
例えば、int型の数をキャストして文字列に変換できるという使い方があることを知っています。
ただ、「transform.Cast<Transform>()」は、「transformをtransformにキャスト?」しているのでしょうか?
「何をしているかわかっていない」ので、「何故、この処理が必要か」ということもわかりません。
また、「unity cast」で検索すると、Collider2Dのキャストしか引っ掛かってこないのですが、Cast<Transform>()のCastのリファレンスってあるのでしょうか?
余談ですが、ForEach内の「x.parent = null;」の処理って必要ですか?
ゲームを実行したら、なくても子オブジェクトが破棄できているような挙動をしました。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
リファレンスには...
また、以下のようにループを使って子の Transform を使用する列挙体をサポートしています。
としか書かれていませんが、Transform
は...
C#
1using System; 2using System.Collections; 3using System.Runtime.CompilerServices; 4using UnityEngine.Bindings; 5using UnityEngine.Internal; 6using UnityEngine.Scripting; 7 8namespace UnityEngine 9{ 10 /// <summary> 11 /// <para>Position, rotation and scale of an object.</para> 12 /// </summary> 13 [NativeHeader("Configuration/UnityConfigure.h")] 14 [NativeHeader("Runtime/Transform/Transform.h")] 15 [NativeHeader("Runtime/Transform/ScriptBindings/TransformScriptBindings.h")] 16 [RequiredByNativeCode] 17 public class Transform : Component, IEnumerable 18 { 19 // 省略 20 21 public IEnumerator GetEnumerator() 22 { 23 return (IEnumerator) new Transform.Enumerator(this); 24 } 25 26 // 省略 27 28 private class Enumerator : IEnumerator 29 { 30 private int currentIndex = -1; 31 private Transform outer; 32 33 public object Current 34 { 35 get 36 { 37 return (object) this.outer.GetChild(this.currentIndex); 38 } 39 } 40 41 internal Enumerator(Transform outer) 42 { 43 this.outer = outer; 44 } 45 46 public bool MoveNext() 47 { 48 return ++this.currentIndex < this.outer.childCount; 49 } 50 51 public void Reset() 52 { 53 this.currentIndex = -1; 54 } 55 } 56 } 57} 58
となっており、IEnumerableインターフェイスを実装しています。
ただしこれはジェネリック版のIEnumerable<Transform>ではないため、そのままではLINQの各種メソッドが使えません。
そこでCast<Transform>を使うとIEnumerable<Transform>
に変わり、LINQが使えるようになります。もしここで、何らかの条件によって削除するTransform
をふるい分けたい...などといった場合には、この後にLINQのメソッドをつなげてやることができるでしょう。
さらにToListでList<Transform>に変えることで、ForEachが使えるようになります。
x.parent = null;
については私も最初は不必要じゃないかと思いましたが、ちょっと違いの出てくる状況を思いつきました。
下記のようなコードで、親の切り離しがある場合とない場合を比較してみると...
C#
1using System.Collections; 2using System.Linq; 3using UnityEngine; 4 5public class DeleteChildrenTest : MonoBehaviour 6{ 7 public GameObject TargetA; 8 public GameObject TargetB; 9 10 private IEnumerator Start() 11 { 12 // x.parent = null;がある場合 13 Debug.Log("--------Detach parent--------"); 14 Debug.LogFormat("Child count:{0}", this.TargetA.transform.childCount); 15 Debug.Log("Children:"); 16 foreach (Transform t in this.TargetA.transform) 17 { 18 Debug.LogFormat("\t{0}", t.name); 19 } 20 Debug.Log("Destroy!"); 21 UnityUtil.DestroyChildren_LinQ(this.TargetA); 22 Debug.LogFormat("Child count:{0}", this.TargetA.transform.childCount); 23 Debug.Log("Children:"); 24 foreach (Transform t in this.TargetA.transform) 25 { 26 Debug.LogFormat("\t{0}", t.name); 27 } 28 29 // x.parent = null;がない場合 30 Debug.Log("--------Keep parent--------"); 31 Debug.LogFormat("Child count:{0}", this.TargetB.transform.childCount); 32 Debug.Log("Children:"); 33 foreach (Transform t in this.TargetB.transform) 34 { 35 Debug.LogFormat("\t{0}", t.name); 36 } 37 Debug.Log("Destroy!"); 38 DestroyChildrenKeepParent(this.TargetB); 39 Debug.LogFormat("Child count:{0}", this.TargetB.transform.childCount); 40 Debug.Log("Children:"); 41 foreach (Transform t in this.TargetB.transform) 42 { 43 Debug.LogFormat("\t{0}", t.name); 44 } 45 46 // 1フレーム待って... 47 yield return null; 48 49 // x.parent = null;がある場合 50 Debug.Log("--------Detach parent--------"); 51 Debug.LogFormat("Child count:{0}", this.TargetA.transform.childCount); 52 Debug.Log("Children:"); 53 foreach (Transform t in this.TargetA.transform) 54 { 55 Debug.LogFormat("\t{0}", t.name); 56 } 57 58 // x.parent = null;がない場合 59 Debug.Log("--------Keep parent--------"); 60 Debug.LogFormat("Child count:{0}", this.TargetB.transform.childCount); 61 Debug.Log("Children:"); 62 foreach (Transform t in this.TargetB.transform) 63 { 64 Debug.LogFormat("\t{0}", t.name); 65 } 66 } 67 68 private static void DestroyChildrenKeepParent(GameObject go) 69 { 70 71 if (go.transform.childCount > 0) 72 { 73 go.transform.Cast<Transform>().ToList().ForEach(x => { GameObject.Destroy(x.gameObject); }); 74 } 75 } 76}
親を切り離さない場合は、1フレーム経ってオブジェクトが削除されるまでは、子のDestroy
後でも子を列挙することができました。
投稿2018/11/24 20:29
総合スコア10807
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/11/26 15:22
2018/11/26 22:22
退会済みユーザー
2018/11/27 14:39