Wenn ich in generischem C # codiert habe, kann ich eine Liste erstellen, in der nur ein bestimmter Objekttyp gespeichert ist. Wenn ich versehentlich versuche, der Liste etwas anderes als diesen Typ hinzuzufügen, werde ich umgehend benachrichtigt und kann das Problem schnell beheben.
List<Foo> my_list = new List<Foo>(); my_list.Add(Bar) //Error
Allerdings, weil ich „m Mit Unity muss mein Skript an ein GameObject angehängt und in der Liste gespeichert werden.
List<GameObject> my_list = new List<GameObject>(); GameObject Foo = new GameObject; Foo.AddComponent<Foo>(); GameObject Bar = new GameObject; Bar.AddComponent<Bar>(); my_list.Add(Foo) //Fine my_list.Add(Bar) //Works, but I don"t want it to
Ich möchte nur, dass die Liste „Foo“ speichert „GameObjects (GameObjects mit der Foo-Komponente), aber nichts hindert mich daran, versehentlich irgendeine Art von GameObject zu speichern, was dazu führen könnte (und bereits), dass ich mir stundenlang am Kopf kratzte, um das Problem zu beheben.
Gibt es eine Möglichkeit, ein GameObject so zu unterteilen, dass es den Effekt von List<GameObject(Foo)> my_list
hat? Gibt es eine Möglichkeit, dies auch mit Arrays zu tun?
Antwort
Wenn Sie nur GameObject
-Typen speichern möchten, die einen bestimmten Component
Element, die einfachste Lösung besteht darin, das spezifische Component
für den Listentyp zu verwenden.
Das b Die Klasse ase Component
enthält einen Verweis auf die „host GameObject
„. Wenn Sie Ihre Liste auf das spezifische Component
beschränken, erhalten Sie weiterhin Zugriff auf die jeweiligen GameObject
.
Die Das folgende Skript ist ein Beispiel dafür, wie Sie dies für die generische Klasse Collider
verwalten würden. Ich habe eine Methode speziell zum Hinzufügen des Elements eingefügt, die eine bool
zurückgibt, um zu bestätigen, ob tatsächlich eine Collider
auf der GameObject
und eine Methode speziell zum direkten Abrufen der erforderlichen GameObject
basierend auf einem Index in der Liste.
///<summary>A list of generic collider types, populated through the inspector.</summary> public List<Collider> colliders; ///<summary>Adds a collider reference to the list, using the host game object.</summary> ///<param name="targetGameObject">The game object to reference the collider from./<param> ///<returns>True, if the game object contained a collider, else returns false.</returns> public bool AddGameObjectToList(GameObject targetGameObject) { Collider targetCollider = GameObject.GetComponent<Collider>(); if(targetCollider == null) { return false; } else { colliders.Add(target collider); return true; } } <summary>Provides direct reference to the game object of a certain element in the list.</summary> ///<param name="index">The index pointer to the collider holding the desired game object.<param> ///<returns>The game object associated with the provided index in the component list.</returns> public GameObject GetGameObject(int index) { return colliders[index].GameObject; }
Für Bonuspunkte können Sie dies mithilfe von Generika in eine Basisklasse verwandeln. Wenn Sie ein Generikum verwenden, das basiert in der Klasse Component
ist, können Sie Instanzen im laufenden Betrieb erstellen, um jede Komponente darzustellen. Alle Komponenten erben von Component
.
Antwort
- Verhalten für jeder Typ. d.h. foo.cs, bar.cs usw.
- Erstellen Sie den gewünschten Listentyp. d. h. List Foolist
-
Wenn Sie nun versuchen, eine Balkeninstanz zu foo hinzuzufügen, wird ein Fehler ausgegeben.
public Transform fooObjects; List<Foo> fooList; Bar b; // Use this for initialization void Awake () { fooList = new List<Foo>(); foreach (Transform item in fooObjects) { Foo f = item.gameObject.GetComponent<Foo>(); if(f != null) { fooList.Add(f); } else { Debug.Log("There are some object which is not FOO"); } } b = new Bar(); } void OnEnable () { foreach (var item in fooList) { item.gameObject.transform.name = "THIS IS FOO"; } fooList.Add(b); // this will throw an error in the debug window. }
Ich hoffe das hilft. Wenn es nicht genug ist, geben Sie bitte hier einen Kommentar ab. Danke