-2

Instead of writing a code like

FindObjectOfType<GameManager>().gameOver()

I would like to type just

gm.gameOver()

Is there a way to do that in Unity?

Maybe using some kind of alias, or some kind of namespace or something else. I am after making my code clean, so using GameManger gm = FindObjectOfType() in every file that uses a the GameManager is not what I am looking for.

Bob Ueland
  • 1,658
  • 14
  • 20

1 Answers1

5

In general I have to discourage this question. This is very questionable and I would actually not recommend this kind of shortening aliases for types and especially not for a complete method call ... bad enough when it is done with variables and fields by a lot of people.

Always use proper variable and field names thus that by reading the code you already know what you are dealing with!


how about storing it in a variable (or class field) at the beginning or whenever needed (but as early as possible)

// You could also reference it already in the Inspector
// and skip the FindObjectOfType call entirely
[SerializeField] private _GameManager gm; 

private void Awake() 
{ 
    if(!gm) gm = FindObjectOfType<_GameManager>(); 
} 

and then later use

gm.gameOver();

where needed.

In general you should do this only once because FindObjectOfType is a very performance intense call.

This has to be done of course for each class wanting to use the _GameManager instance ...

However this would mostly be the preferred way to go.


Alternatively you could also (ab)use a Singleton pattern ... it is controversial and a lot of people hate it kind of ... but actually in the end FindObjectOfType on the design side does kind of the same thing and is even worse in performance ...

public class _GameManager : MonoBehaviour
{
    // Backing field where the instance reference will actually be stored
    private static _GameManager instance;

    // A public read-only property for either returning the existing reference
    // finding it in the scene
    // or creating one if not existing at all
    public static _GameManager Instance
    {
        get 
        {
            // if the reference exists already simply return it
            if(instance) return instance;

            // otherwise find it in the scene
            instance = FindObjectOfType<_GameManager>();

            // if found return it now
            if(instance) return instance;

            // otherwise a lazy creation of the object if not existing in scene
            instance = new GameObject("_GameManager").AddComponent<_GameManager>();

            return instance;
        }
    }

    private void Awake()
    {
        instance = this;
    }
}

so you can at least reduce it to

_GameManager.Instance.gameOver();

the only alias you can create now would be using a using statement at the top of the file like e.g.

using gm = _GameManager;

then you can use

gm.Instance.gameOver();

it probably won't get much shorter then this.

But as said this is very questionable and doesn't bring any real benefit, it only makes your code worse to read/maintain! What if later in time you also have a GridManager and a GroupMaster? Then calling something gm is only confusing ;)


Btw you shouldn't start types with a _ .. rather call it e.g. MyGameManager or use a different namespace if you wanted to avoid name conflicts with an existing type

derHugo
  • 49,310
  • 9
  • 37
  • 73
  • Why is the singleton pattern controversial? I use it a lot and it is a great way of keeping track of things, should I not use it? – barteezy Nov 04 '19 at 08:23
  • 2
    @barteezy for Unity I also often use it but people will direct you to posts like [this one](https://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons) ;) – derHugo Nov 04 '19 at 08:25
  • so instead of writing one line FindObjectOfType().gameOver();, I now have to write GameManager gm; ... void Awake() { if(!gm) { gm = FindObjectOfType(); } } ... gm.gameOver() – Bob Ueland Nov 04 '19 at 08:27