Om jag kodade i generisk C # kan jag skapa en lista som bara lagrar en viss typ av objekt. Om jag av misstag försöker lägga till något annat än den typen i listan får jag omedelbart besked och kan åtgärda problemet snabbt.
List<Foo> my_list = new List<Foo>(); my_list.Add(Bar) //Error
Men eftersom jag ”m med hjälp av Unity måste mitt skript bifogas ett GameObject, och det måste lagras i listan.
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
Jag vill bara att listan ska lagra ”Foo ”GameObjects (GameObjects med Foo-komponenten), men det finns inget som hindrar mig från att oavsiktligt lagra någon typ av GameObject, vilket kan (och redan har) orsakat att jag klättrade i timmar och försök att felsöka problemet.
Finns det ett sätt att undertypa ett GameObject så att det får effekten av List<GameObject(Foo)> my_list
? Finns det ett sätt att göra det med arrays också?
Svara
Om du bara vill lagra GameObject
typer som innehåller en specifik Component
element, den enklaste lösningen är att använda den specifika Component
för listtypen.
B ase Component
klass innehåller en hänvisning till ”värd GameObject
”. Att begränsa din lista till det specifika Component
ger dig fortfarande tillgång till respektive GameObject
.
nedanstående skript är ett exempel på hur du skulle hantera detta för den generiska Collider
-klassen. Jag har inkluderat en metod specifikt för att lägga till elementet, som returnerar en bool
för att bekräfta om en Collider
faktiskt hittades på GameObject
, och en metod specifikt för att direkt hämta den nödvändiga GameObject
baserat på ett index i listan.
///<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 bonuspoäng kan du förvandla detta till en grundklass med generik. Med hjälp av en generik som är baserad i klassen Component
kan du skapa förekomster i farten för att representera någon komponent; alla komponenter ärver från Component
.
Svar
- Gör beteende för varje typ. dvs foo.cs, bar.cs etc
- Skapa önskad typ av lista. dvs lista idioter
-
nu om du försöker lägga till barinstans till foo kommer det att ge ett fel.
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. }
Jag hoppas att det hjälper. Om det inte räcker, ge en kommentar här. Tack