Als ik zou coderen in algemene C #, kan ik een lijst maken die alleen een bepaald type object opslaat. Als ik per ongeluk iets anders dan dat type aan de lijst probeer toe te voegen, wordt mij dit onmiddellijk verteld en kan ik het probleem snel oplossen.
List<Foo> my_list = new List<Foo>(); my_list.Add(Bar) //Error
Maar omdat ik “m bij gebruik van Unity moet mijn script aan een GameObject worden gekoppeld, en dat moet in de lijst worden opgeslagen.
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
Ik wil alleen dat de lijst “Foo “GameObjects (GameObjects met de Foo-component), maar er is niets dat me ervan weerhoudt om per ongeluk een GameObject op te slaan, wat me urenlang kon (en heeft) gekrabd om het probleem op te lossen.
Is er een manier om een GameObject te subtypen zodat het het effect heeft van List<GameObject(Foo)> my_list
? Is er ook een manier om dit met arrays te doen?
Antwoord
Als u alleen GameObject
typen wilt opslaan die een specifieke Component
element, is de eenvoudigste oplossing om het specifieke Component
voor het lijsttype te gebruiken.
De b ase Component
klasse bevat een verwijzing naar de “host GameObject
“. Door uw lijst te beperken tot het specifieke Component
, krijgt u nog steeds toegang tot elke respectieve GameObject
.
De het onderstaande script is een voorbeeld van hoe u dit zou beheren voor de algemene klasse Collider
. Ik heb een methode toegevoegd specifiek voor het toevoegen van het element, die een bool
retourneert om te bevestigen of een Collider
daadwerkelijk is gevonden op de GameObject
, en een methode specifiek voor het direct ophalen van de vereiste GameObject
op basis van een index in de lijst.
///<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; }
Voor bonuspunten zou je dit in een basisklasse kunnen veranderen door generieke middelen te gebruiken. Het gebruik van een generiek die gebaseerd is in de klasse Component
, stelt je in staat om direct instances te creëren die elk component vertegenwoordigen; alle componenten erven van Component
.
Antwoord
- Maak gedrag voor elk type. d.w.z. foo.cs, bar.cs enz.
- Maak het gewenste type lijst. d.w.z. List foolist
-
als je nu een bar-instantie aan foo probeert toe te voegen, zal het een foutmelding geven.
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. }
Ik hoop dat dat helpt. Als dit niet genoeg is, geef dan hier een opmerking. Bedankt