Find() vs static variable that constains GameObject vs static method that returns GameObject

This probably is one of the quetions in the series of “It really doesn’t matter / use what you prefer”, but is there any difference which way I get GameObject that isn’t already in scene (can’t be dragged to Inspector).

Simplified situation:
I have 2 scenes and GameObject called Data is created on first scene and is set as “DontDestroyOnLoad”. I need to access script in this Data GameObject at seconds scene, but I need to get it first somehow.


Solution 1:

Simply use Find() to get it.

//Some other script in some other object
public GameObject data;

void Awake()
{
    data = GameObject.Find("Data");
}

Solution 2:

In script that is attached to Data GameObject create static variable that contains itself.

//Data.cs
static public GameObject thisObj;

void Awake()
{
    data = gameObject;
}

//In some other script in some other object
public GameObject data;

void Awake()
{
    data = Data.thisObj;
}

Solution 3:

In script that is attached to Data GameObject create static method that returns itself;

//Data.cs
static public GameObject GetGameObject()
{
    return gameObject;
}

//In some other script in some other object
public GameObject data;

void Awake()
{
    data = Data.GetGameObject();
}

Which of these would you use and why or is there some better way to do this? I have mostly used the first solution, but technically solutions 2 and 3 might be somewhat better as Find() is kinda slow. I have been trying to avoid using static if there is some other solution as have had some strange issues with excessive static usage.

Following tradition, I will award the prizes in reverse order…

“Solution” 3.

Have you tried this? It won’t compile because Data.gameObject (inherited from MonoBehaviour, presumably) is not static and therefore not accessible from your static function.

Solution 2.

This code is dangerous. It is essentially a highly-simplified version of a design pattern called “Singleton”, which is a way of achieving what you’re after. But you should research Singletons before trying to use one; you will find that they are dangerous if not implemented carefully. This is partly due to their use of statics - you are correct to conclude from your experience that statics should be used sparingly.

Solution 1.

Find-ing may not be recommended if it needs to be performed regularly. But doing it once, when your scene loads, is not a big deal.

I would go with this one for now as it is quick and easy and not too dangerous so long as you only create the one object with that name.

Note that you could also choose to Find it by Component-type or by Tag. The former would be the most robust way of doing things if you only have one of them, whereas using names and/or tags would allow you to have multiple instances.

You might also consider looking into the proper way to implement a Singleton MonoBehaviour class (you’ll find examples by searching). But like I said, be careful. If you do it wrong (as you have), it might appear to work only to create severe problems later on.

In practice, I’ve found it easiest to use a single global static pointer to the script, sort of like your item 2:

class commonStuffA : MonoB {
  public static commonStuffA ptr;
  void Awake() { ptr=this; }

  public Texture2D T1; // set in Inspector
  public void usefulFunc() {}
}

And then anyone can use it, nothing extra needed, with commonStuffA.ptr.usefulFunc();.