- Home /
Multiple FindObjectOfType to the same object, best practice
Hi, I am referencing a central script from another script multiple times, something like this:
FindObjectOfType<GameSession>().activeEngine = 0;
FindObjectOfType<GameSession>().mainGun = 0;
FindObjectOfType<GameSession>().activeGun = 0;
I was wondering if there's a more efficient way ?
Answer by Bunny83 · Sep 17, 2019 at 12:02 PM
Just cache the reference once and then reuse it.
GameSession gs = FingObjectOfType<GameSession>();
gs.activeEngine = 0;
gs.mainGun = 0;
gs.activeGun = 0;
Of course if you have to reference this script from multiple places and there is always only one instance it's better to implement a MonoBehaviour based singleton. Inside your GameSession class:
public GameSession : MonoBehaviour
{
private static GameSession m_Instance = null;
public static GameSession Instance
{
get
{
if (m_Instance == null)
{
m_Instance = FingObjectOfType<GameSession>();
m_Instance.transform.parent = null;
DontDestroyOnLoad(m_Instance.gameObject);
}
return m_Instance;
}
}
// the rest of your script
}
Now you can simply use
GameSession.Instance.activeEngine = 0;
GameSession.Instance.mainGun = 0;
GameSession.Instance.activeGun = 0;
from any other script. It will automaticalls call FindObjectOfType the first time you use the Instance property. From that point on it will only return the already cached reference.
Note the lines
m_Instance.transform.parent = null;
DontDestroyOnLoad(m_Instance.gameObject);
just ensure that the object will stay alive when you change the scene. However if you have an instance of your GameSession in each scene this would cause issues when you load a new scene. If you want the GameSession to be destroyed at a scene change, just remove those two lines.
This makes the code much cleaner! thanks! i was using a different singleton script for my "GameSession" but without the static variables, dont i need to place the singleton inside an OnAwake() function or something like that?
also 1 small thing, if i destory the GameSession at the end of the game, and instantiate a new one just at the start of the game, can i still use the singleton with the static variables?
Yes, you can use this singleton pattern since the null check will detect destroyed objects thanks to Unity's custom == operator. However destroying and recreating a singleton can cause issues depending on the order of your code. If the singleton is destroyed and some code tries to access the singleton which has not yet been recreated will of course cause problems. If the class doesn't need any serialized values you could even create a second stage when the FingObjectOfType fails it would automatically create an instance. This doesn't always make sense for all kinds of singletons. Though if your class allows this you can do this ins$$anonymous$$d:
get
{
if (m_Instance == null)
{
m_Instance = FingObjectOfType<GameSession>();
if (m_Instance == null)
m_Instance = (new GameObject("GameSession")).AddComponent<GameSession>();
m_Instance.transform.parent = null;
DontDestroyOnLoad(m_Instance.gameObject);
}
return m_Instance;
}
This will first check if we have a cached instance that is still alive. If not it will search for one using FingObjectOfType. If no instance is found it will simply create a new gameobject with that script attached.
Note that if your class doesn't need any Unity callbacks it probably shouldn't be a $$anonymous$$onoBehaviour in the first place. $$anonymous$$onoBehaviours have quite a bit more overhead compared to a normal C# class. Though we don't know enough about your class to suggest any particular version.
Thanks for the explanation! I'm Quite of a noob programmer so i use $$anonymous$$onoBehaviour for everything since i thought every reference to gameObjects needs to be in $$anonymous$$onoBehaviour... what is a unity callback and what isn't is a huge topic on it on :))
So which one will be a good practice
void start()
{
GameSession gs = FingObjectOfType<GameSession>();
gs.activeEngine = 0;
gs.mainGun = 0;
gs.activeGun = 0;
}
or
public static GameSession instance;
private void Awake()
{
instance = this;
}
something = GameSession.instance.objectreference; // this reference in other script
Your answer
![](https://koobas.hobune.stream/wayback/20220612212246im_/https://answers.unity.com/themes/thub/images/avi.jpg)