Finding Game Objects and Components is now easier using this simple pattern

I have some fun here
for those who search for game objects and components in the scenes using
[GameObject](http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=GameObject).[Find](http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=Find)("") , FindObjectOfType<> , GetComponent<> or any other searching method. and since searching for objects and components is a high cost operation and annoying for some people. This is a very simple and easy pattern that will make the process easier.
We start with making a class StaticObject
which holds the game object, its name, and a reference to its components that we will need to use. and then we create a class
AllStaticObjects
which holds a list of the
StaticObject
to assign in the inspector, and an indexer to search for the desired game object by its name.

Second step is creating a class
StaticObjectComponent
which holds a component and its name. then a class
AllComponents
which holds a list of
StaticObjectComponent
to assign in the inspector, and an indexer to search for the desired component by its name.

Of course we don’t forget to mark all the classes as
[System.Serializable]
so that they be displayed in the inspector.

In our manager script, we make a singleton, and a public reference to
AllStaticObjects
class to assign them from the inspector.

Now, if want to access a game object you can just type it like this :
[GameObject](http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=GameObject) ui = ([GameObject](http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=GameObject)) StaticObjectsManager.Instance.AllObjects["UI Canvas"].TheGameObject;

if you want to access a component, you will type it like this :
var animation = ([A](http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=GameObject)nimation) StaticObjectsManager.Instance.AllObjects["UI Canvas"].AllComponents["Animation"].Component;

This is the full code

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class AllStaticObjects
{
    public List<StaticObject> Objects;

    public StaticObject this[string name]
    {
        get
        {
            foreach (StaticObject staticObject in Objects)
            {
                if (staticObject.Name == name)
                {
                    return (staticObject);
                }
            }

            throw (new MissingReferenceException("The game object with name -" + name + "- is not found"));
        }
    }
}

[System.Serializable]
public class StaticObject
{
    public string Name;
    public GameObject TheGameObject;
    public AllComponents AllComponents;
}

[System.Serializable]
public class AllComponents
{
    public List<StaticObjectComponent> Components;

    public StaticObjectComponent this[string name]
    {
        get
        {
            foreach (StaticObjectComponent component in Components)
            {
                if (component.Name == name)
                {
                    return (component);
                }
            }

            throw (new MissingReferenceException("The component with name -" + name + "- is not found in the game object " + name));
        }
    }
}

[System.Serializable]
public class StaticObjectComponent
{
    public string Name;
    public Component Component;
}

public class StaticObjectsManager : MonoBehaviour
{
    public static StaticObjectsManager Instance;

    #region Singleton
    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
    #endregion

    #region Game Objects
    public AllStaticObjects AllObjects;
    #endregion
}

I mean, you’re still looping over all instances. All you’ve done is reduce the number of instances you have to loop.

Also, if you’re going to be generating a name/value pair, might as well use a Dictionary<string, Component> and get O(1) look-up speeds.

This could be defined generically as follows:

public static class Lookup<T>
{
   
    private static Dictionary<string, T> _table = new Dictionary<string, T>();
   
    public static void Register(string nm, T obj)
    {
        _table[nm] = obj;
    }
   
    public static void Unregister(string nm)
    {
        _table.Remove(nm);
    }
   
    public static T Find(string nm)
    {
        T result;
        if(_table.TryGetValue(nm, out result))
            return result;
        else
            return default(T);
    }
   
}

And any script that uses it can do this in their Awake/OnDestroy methods:

public class SomeScript : MonoBehaviour
{
   
    void Awake()
    {
        Lookup<SomeScript>.Register(this.name, this);
    }
   
    void OnDestroy()
    {
        Lookup<SomeScript>.Unregister(this.name);
    }
   
}

Of course, this isn’t usually how I do this personally.

Hmm… I think you are simply wrapping the underlying high-performance Unity C++ engine’s name and content lookup system with your own bespoke system written in C#… not sure why any of this would be worth doing unless you just like typing lots of boilerplate code. :slight_smile:

4 Likes