Se stessi codificando in C # generico posso creare un elenco che memorizza solo un certo tipo di oggetto. Se provo accidentalmente ad aggiungere qualcosa di diverso da quel tipo allelenco, mi verrà prontamente informato e posso risolvere il problema rapidamente.
List<Foo> my_list = new List<Foo>(); my_list.Add(Bar) //Error
Tuttavia, perché “m utilizzando Unity il mio script deve essere allegato a un GameObject e questo deve essere memorizzato nellelenco.
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
Voglio che lelenco memorizzi solo “Foo “GameObjects (GameObjects with the Foo component), tuttavia non cè nulla che mi impedisca di memorizzare accidentalmente qualsiasi tipo di GameObject, il che potrebbe (e ha già) causato ore e ore a grattarmi la testa cercando di risolvere il problema.
Cè un modo per sottotipizzare un GameObject in modo che abbia leffetto di List<GameObject(Foo)> my_list
? Cè un modo per farlo anche con gli array?
Rispondi
Se desideri memorizzare solo GameObject
tipi che contengono uno specifico Component
, la soluzione più semplice è utilizzare lelemento Component
specifico per il tipo di elenco.
Il b La classe ase Component
contiene un riferimento a “host GameObject
“. Limitare lelenco allo specifico Component
ti darà comunque accesso a ciascun rispettivo GameObject
.
Il lo script sottostante è un esempio di come gestireste questo per la classe generica Collider
. Ho incluso un metodo specifico per aggiungere lelemento, che restituirà un bool
per confermare se un Collider
è stato effettivamente trovato su GameObject
e un metodo specifico per recuperare direttamente il GameObject
richiesto basato su un indice nellelenco.
///<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; }
Per i punti bonus, potresti trasformarlo in una lezione di base, usando i generici. Lutilizzo di un generico basato nella classe Component
consente di creare istanze al volo per rappresentare qualsiasi componente; tutti i componenti ereditano da Component
.
Risposta
- Comportamento per ogni tipo. Ad esempio foo.cs, bar.cs ecc
- Crea il tipo di elenco desiderato. cioè List foolist
-
ora se provi ad aggiungere listanza di bar a foo, allora darà un errore.
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. }
Spero che questo aiuti. Se non è abbastanza, per favore lascia un commento qui. Grazie