Hi,
We have the following lines of code in a C# script:
public GameObject ButtonSelectorLeftSprite;
ButtonSelectorLeftSprite = GameObject.Find("ButtonSelectorLeft");
Above works fine, but am wondering if it’s OK to use?
(thought we saw something somewhere that said “GameObject.Find” is VERY slow?)
We don’t see any performance hit from using the above, but am wondering if its wide use should be avoided?
If it should be avoided then please let us know what else we should be using…
Let us know, thanks!
Jesse
You can certainly use this, despite all the funny crazy people all over the net howling about how slow it is while their eyes roll back in their heads like rabid zombies.
As you observed, it’s not actually “very slow” at all. It’s only slow if you’re doing it every frame, and if you have a lot of them doing it every frame. Somehow I doubt you have that many buttons.
It’s all in how you use it. If you’re doing it in Start() you’re just fine. Even if you’re doing it upon every time the user clicks the mouse, you’ll be just fine. People just don’t click that often, given the vast majority of user interfaces.
Here’s some pros and cons:
pro:
- no need to remember where to drag stuff in Unity
- you are immune to the usual meta file / prefab damage “Missing reference” errors
- it’s easy to see your work in a commit log diff in source control.
con:
- if someone renames that GameObject, or creates another with the same name, your code breaks in sometimes mysterious ways
- the above means you need to be disciplined with naming: don’t call it “Button” but rather “ButtonSelectorLeft”, as you have done.
NOTE: unless someone else needs it, you no longer need to declare your variable as public, if it’s being manipulated entirely within the given script.
Full script is below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ButtonActions : MonoBehaviour
{
GameObject ButtonSelectorLeftSprite;
GameObject ButtonSelectorRightSprite;
Vector3 position;
public void doSTARTGame()
{
GlobalVariables.NextScreenToDisplay = 2;
GlobalVariables.ScreenFadeStatus = GlobalVariables.FadeOut;
ButtonSelectorLeftSprite = GameObject.Find("ButtonSelectorLeft");
position = ButtonSelectorLeftSprite.transform.position;
position.y = (110.0f / 100.0f);
ButtonSelectorLeftSprite.transform.position = position;
ButtonSelectorRightSprite = GameObject.Find("ButtonSelectorRight");
position = ButtonSelectorRightSprite.transform.position;
position.y = (110.0f / 100.0f);
ButtonSelectorRightSprite.transform.position = position;
GlobalVariables.SoundEffectToPlay = 2;
}
public void doSOptions()
{
GlobalVariables.NextScreenToDisplay = 3;
GlobalVariables.ScreenFadeStatus = GlobalVariables.FadeOut;
ButtonSelectorLeftSprite = GameObject.Find("ButtonSelectorLeft");
position = ButtonSelectorLeftSprite.transform.position;
position.y = (60.0f / 100.0f);
ButtonSelectorLeftSprite.transform.position = position;
ButtonSelectorRightSprite = GameObject.Find("ButtonSelectorRight");
position = ButtonSelectorRightSprite.transform.position;
position.y = (60.0f / 100.0f);
ButtonSelectorRightSprite.transform.position = position;
GlobalVariables.MusicToPlay = 10;
GlobalVariables.SoundEffectToPlay = 2;
}
public void doHowToPlay()
{
GlobalVariables.NextScreenToDisplay = 4;
GlobalVariables.ScreenFadeStatus = GlobalVariables.FadeOut;
ButtonSelectorLeftSprite = GameObject.Find("ButtonSelectorLeft");
position = ButtonSelectorLeftSprite.transform.position;
position.y = (10.0f / 100.0f);
ButtonSelectorLeftSprite.transform.position = position;
ButtonSelectorRightSprite = GameObject.Find("ButtonSelectorRight");
position = ButtonSelectorRightSprite.transform.position;
position.y = (10.0f / 100.0f);
ButtonSelectorRightSprite.transform.position = position;
GlobalVariables.SoundEffectToPlay = 2;
}
public void doHighScores()
{
GlobalVariables.NextScreenToDisplay = 5;
GlobalVariables.ScreenFadeStatus = GlobalVariables.FadeOut;
ButtonSelectorLeftSprite = GameObject.Find("ButtonSelectorLeft");
position = ButtonSelectorLeftSprite.transform.position;
position.y = (-40.0f / 100.0f);
ButtonSelectorLeftSprite.transform.position = position;
ButtonSelectorRightSprite = GameObject.Find("ButtonSelectorRight");
position = ButtonSelectorRightSprite.transform.position;
position.y = (-40.0f / 100.0f);
ButtonSelectorRightSprite.transform.position = position;
GlobalVariables.SoundEffectToPlay = 2;
}
public void doAbout()
{
GlobalVariables.NextScreenToDisplay = 6;
GlobalVariables.ScreenFadeStatus = GlobalVariables.FadeOut;
ButtonSelectorLeftSprite = GameObject.Find("ButtonSelectorLeft");
position = ButtonSelectorLeftSprite.transform.position;
position.y = (-90.0f / 100.0f);
ButtonSelectorLeftSprite.transform.position = position;
ButtonSelectorRightSprite = GameObject.Find("ButtonSelectorRight");
position = ButtonSelectorRightSprite.transform.position;
position.y = (-90.0f / 100.0f);
ButtonSelectorRightSprite.transform.position = position;
GlobalVariables.SoundEffectToPlay = 2;
}
public void doExitGame()
{
Application.Quit();
ButtonSelectorLeftSprite = GameObject.Find("ButtonSelectorLeft");
position = ButtonSelectorLeftSprite.transform.position;
position.y = (-140.0f / 100.0f);
ButtonSelectorLeftSprite.transform.position = position;
ButtonSelectorRightSprite = GameObject.Find("ButtonSelectorRight");
position = ButtonSelectorRightSprite.transform.position;
position.y = (-140.0f / 100.0f);
ButtonSelectorRightSprite.transform.position = position;
GlobalVariables.SoundEffectToPlay = 2;
}
public void doBackToTitle()
{
GlobalVariables.NextScreenToDisplay = 2;
GlobalVariables.ScreenFadeStatus = GlobalVariables.FadeOut;
GlobalVariables.MusicToPlay = 0;
GlobalVariables.SoundEffectToPlay = 2;
}
}
I think @Kurt-Dekker is downplaying the badness of GameObject.Find, and it’s not about speed. There are many, many more scenarios where GameObject.Find will fail, and the reasons often have nothing to do with speed. If you ever have a second copy of the window in which that button exists, for example, GameObject.Find will become fundamentally unworkable with that new object. If you ever make that button a prefab and spawn it with Instantiate, it will have (Clone) on the end and Gameobject.Find won’t work. There are literally dozens of different ways you might change your project in the future that will make GameObject.Find break. It’s slow, sure, but it’s far more important that it’s fragile.
And also, I have in 14 years of using Unity, literally never come across a situation where an alternate way of finding a reference to the object wasn’t objectively better than GameObject.Find, with only two exceptions: 1) Editor scripts; and 2) me not yet knowing about the better options. The second one is a big part of why I wrote the above-linked article, which has a good half-dozen different techniques for different situations, and between those you should be able to easily replace any instance of GO.F.
In your specific case, it looks like you’d be better off with fixed references that are assigned in the Inspector. There’s also a ton of redundant code there that you may want to put into functions instead of copying and pasting.
1 Like
@StarManta
Hi,
What is a good replacement for “GameObject.Find”?
Also, we changed the code below to what you suggested:
Thanks!
Jesse
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ButtonActions : MonoBehaviour
{
GameObject ButtonSelectorLeftSprite;
GameObject ButtonSelectorRightSprite;
Vector3 position;
public void SetupButton(int nextScreen, float posY)
{
GlobalVariables.NextScreenToDisplay = nextScreen;
GlobalVariables.ScreenFadeStatus = GlobalVariables.FadeOut;
ButtonSelectorLeftSprite = GameObject.Find("ButtonSelectorLeft");
position = ButtonSelectorLeftSprite.transform.position;
position.y = (posY / 100.0f);
ButtonSelectorLeftSprite.transform.position = position;
ButtonSelectorRightSprite = GameObject.Find("ButtonSelectorRight");
position = ButtonSelectorRightSprite.transform.position;
position.y = (posY / 100.0f);
ButtonSelectorRightSprite.transform.position = position;
GlobalVariables.SoundEffectToPlay = 2;
}
public void doSTARTGame()
{
SetupButton(2, 110.0f);
}
public void doOptions()
{
SetupButton(3, 60.0f);
GlobalVariables.MusicToPlay = 10;
}
public void doHowToPlay()
{
SetupButton(4, 10.0f);
}
public void doHighScores()
{
SetupButton(5, -40.0f);
}
public void doAbout()
{
SetupButton(6, -90.0f);
}
public void doExitGame()
{
Application.Quit();
}
public void doBackToTitle()
{
GlobalVariables.NextScreenToDisplay = 2;
GlobalVariables.ScreenFadeStatus = GlobalVariables.FadeOut;
GlobalVariables.MusicToPlay = 0;
GlobalVariables.SoundEffectToPlay = 2;
}
}
Without knowing your exact setup I can’t say for certain, but I think you probably want to make your two ButtonSelectorLeft/RightSprite variables public, and drag in references in the inspector to link them.
And, nice function usage! Should make it much easier to work with 
Hi,
Project is open-source below:
fallenangelsoftware.com/stuff/files/FerrariF40-Engine/FerrariF40-Engine.zip
Basically we call the above script when the buttons are clicked.
Jesse
