Gdybym pisał w ogólnym C #, mógłbym utworzyć listę, która przechowuje tylko określony typ obiektu. Jeśli przypadkowo spróbuję dodać do listy coś innego niż ten typ, otrzymam natychmiastową informację i będę mógł szybko rozwiązać problem.
List<Foo> my_list = new List<Foo>(); my_list.Add(Bar) //Error
Jednak ponieważ używając Unity mój skrypt musi być dołączony do GameObject, a ten musi być zapisany na liście.
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
Chcę, aby lista zawierała tylko „Foo „GameObjects (GameObjects ze składnikiem Foo), jednak nic nie stoi na przeszkodzie, żebym przypadkowo przechował dowolny typ GameObject), co mogło (i już spowodowało) drapanie mnie w głowę podczas próby debugowania problemu.
Czy istnieje sposób na podtyp GameObject, tak aby działał jak List<GameObject(Foo)> my_list
? Czy istnieje sposób, aby to zrobić również z tablicami?
Odpowiedź
Jeśli chcesz przechowywać tylko GameObject
typy, które zawierają określone Component
, najłatwiejszym rozwiązaniem jest użycie określonego Component
dla typu listy.
ase Component
zawiera odniesienie do klasy „host GameObject
„. Ograniczenie listy do konkretnych Component
nadal da ci dostęp do każdego odpowiedniego GameObject
.
Poniższy skrypt jest przykładem tego, jak można sobie z tym poradzić dla ogólnej klasy Collider
. Dołączyłem metodę specjalnie dodawania elementu, która zwróci bool
w celu potwierdzenia, czy Collider
został faktycznie znaleziony w GameObject
oraz metodę przeznaczoną specjalnie do bezpośredniego pobierania wymaganego GameObject
na podstawie indeksu na liście.
///<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; }
Aby otrzymać dodatkowe punkty, możesz przekształcić to w klasę podstawową, używając typów ogólnych. Użycie klasy ogólnej, która jest oparta w klasie Component
, umożliwia tworzenie instancji w locie, które reprezentują dowolny komponent; wszystkie składniki dziedziczą po Component
.
Odpowiedź
- Zachowanie dla każdy typ. tj. foo.cs, bar.cs itp.
- Utwórz listę żądanego typu. tj. List foolist
-
teraz, jeśli spróbujesz dodać instancję bar do foo, spowoduje to błąd.
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. }
Mam nadzieję, że to pomoże. Jeśli to nie wystarczy, zostaw komentarz tutaj. Dzięki