I'd recommend against finding GameObjects by name (using GameObject.Find
or transform.Find
as suggested in the existing answers) whenever you can avoid it.
In my experience this tends to lead to brittle relationships between scripts that are easy to break accidentally, and other more exotic bugs.
The most reliable method, if you have a script that needs to use a particular InputField
and Slider
, is to give it public/serialized fields of these types:
public class MyUIForm : MonoBehaviour
{
public InputField inputField;
public Slider slider;
...
...and wire them up in the Inspector.
This makes the dependency between these objects explicit to anyone using the editor - as soon as you attach this script, the Inspector tells you what it needs.
This dependency is also visible to Unity so it knows which assets need to be included together in a build, if they're not all scene objects. And these references are populated immediately when the object is loaded, which avoids common order-of-execution problems when one script tries to access fields of another one that hasn't had time to Start()
yet.
Adding another object of the same type or the same name or changing the parenting hierarchy won't accidentally break this, because the object has a direct reference. Even in a scene with 100 similarly-named/functioning objects, you have the ability to specify the exact one you want.
If these objects don't exist in the same scene, you can also create intermediate scripts that hold these references. eg. a MainMenu
script that knows about each of its child pages like HighScoresMenu
and SettingsMenu
, and SettingsMenu
holding references to its inputs PlayerNameField
and GammaSlider
. Then if another script needs access to these fields (not sure why - any script using them should probably live in SettingsMenu
, but let's assume there's a good reason) - it can get a reference to the MainMenu
instance and use mainMenu.settingsMenu.gammaSlider
. These intermediate scripts are cheap, and save the rest of your code from needing to know the guts of how your menu is organized in the hierarchy, as well as centralizing the work of wiring up scripts in the inspector.
If you want to wire it up more automatically, you can also use GetComponentInChildren:
public Canvas mainMenu;
private InputField _inputField;
void Start()
{
_inputField = mainMenu.GetComponentInChildren<InputField>();
}
This will search the child hierarchy of mainMenu
, including grandchildren and so on, until it finds something with an InputField
component and return that. (You can also use GetComponentsInChildren to get an array of all matches)
This has some of the same problems as finding an object by name (moving the InputField
to a new parent could cause us to miss it; adding another unrelated InputField
could cause us to grab the wrong one), but we do know we're getting the right type back. It also won't be broken by someone trying to improve readability by changing the object named "InputField" to be named "PlayerNameInput" or just fixing a typo/capitalization.
When used with your own types that are explicit about their use, like the SettingsMenu
example above, these risks largely disappear. You might create a form with two InputField
s, but you're unlikely to ever use two copies of the SettingsMenu
, so if the MainMenu
script used GetComponentInChildren
to find it instead of a direct reference, it's unlikely to ever be broken accidentally.