0
\$\begingroup\$

If I were coding in generic C# I can create a list that only stores a certain type of object. If I accidentally try to add anything other than that type to the list I will be promptly told and can fix the problem quickly.

List<Foo> my_list = new List<Foo>();
my_list.Add(Bar) //Error

However because I'm using Unity my script needs to be attached to a GameObject, and that needs to be stored in the 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

I only want the list to store "Foo" GameObjects (GameObjects with the Foo component), however there is nothing to stop me accidentally storing any type of GameObject, which could (and already has) caused me hours scratching my head trying to debug the problem.

Is there a way to subtype a GameObject so that it has the effect of List<GameObject(Foo)> my_list? Is there a way to do it with arrays too?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

If you only want to store GameObject types that contain a specific Component element, the easiest solution is to use the specific Component for the list type.

The base Component class contains a reference to the "host GameObject". Limiting your list to the specific Component will still give you access to each respective GameObject.


The below script is an example of how you would manage this for the generic Collider class. I have included a method specifically for adding the element, which will return a bool to confirm if a Collider was actually found on the GameObject, and a method specifically for directly retrieving the required GameObject based off an index in the 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;
}

For bonus points, you could turn this into a basic class, using generics. Using a generic that is based in the Component class allows you to create instances on the fly to represent any component; all components inherit from Component.

\$\endgroup\$
0
\$\begingroup\$
  1. Make Behaviour for each type. i.e. foo.cs, bar.cs etc
  2. Create your desired type of list. i.e List foolist
  3. now if you try to add bar instance to foo then it will give an error. Adding bar object to foo giving error Description enter image description here enter image description here

    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. 
    }  
    

I hope that helps. If its not enough please give a comment here. Thanks

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .