Dacă aș codifica în C # generic, pot crea o listă care stochează doar un anumit tip de obiect. Dacă încerc din greșeală să adaug ceva în afară de acel tip pe listă, mi se va spune cu promptitudine și pot rezolva problema rapid.
List<Foo> my_list = new List<Foo>(); my_list.Add(Bar) //Error
Cu toate acestea, pentru că „m folosind Unity, scriptul meu trebuie atașat la un GameObject și acesta trebuie stocat în Listă.
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
Vreau doar ca lista să stocheze „Foo „GameObjects (GameObjects cu componenta Foo), cu toate acestea, nu există nimic care să mă împiedice să stochez accidental orice tip de GameObject, ceea ce ar putea (și deja mi-a provocat) să mă zgâri în cap încercând să depanez problema.
Există o modalitate de a subtipa un GameObject astfel încât să aibă efectul List<GameObject(Foo)> my_list
? Există o modalitate de a o face și cu tablouri?
Răspunde
Dacă vrei să stochezi doar GameObject
tipuri care conțin un Component
element, cea mai ușoară soluție este să folosiți Component
specific pentru tipul listei.
Clasa ase Component
conține o referință la „gazdă GameObject
„. Limitarea listei la Component
vă va oferi în continuare acces la fiecare GameObject
respectiv.
scriptul de mai jos este un exemplu al modului în care ați gestiona acest lucru pentru clasa generică Collider
. Am inclus o metodă specifică pentru adăugarea elementului, care va returna un bool
pentru a confirma dacă un Collider
a fost de fapt găsit pe GameObject
și o metodă specifică pentru recuperarea directă a GameObject
necesară pe baza unui index din listă.
///<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; }
Pentru punctele bonus, puteți transforma acest lucru într-o clasă de bază, folosind generice. Utilizarea unui generic bazat în clasa Component
vă permite să creați instanțe din mers pentru a reprezenta orice componentă; toate componentele moștenesc de la Component
.
Răspunde
- Fă Comportament pentru fiecare tip. adică foo.cs, bar.cs etc
- Creați tipul de listă dorit. Adică List prostit
-
acum, dacă încercați să adăugați o instanță de bare la foo, atunci va da o eroare.
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. }
Sper că te va ajuta. Dacă nu este suficient, vă rugăm să dați un comentariu aici. Mulțumesc