3
\$\begingroup\$

I'm using a "toggle visibility" script on many objects in my scene, and in my gameController class I'm storing references to them in an array like this:

public Fields[] fields;

then I access them by the array index:

fields[0].setVisibility(true);

This works fine, but this list is growing and everything is getting unmaintainable.

So I would like to iterate thru the references to the objects, find the script by its game object name, and call the required function setVisibility(state).

A call, if possible should look like this:

GameObjectName.ScriptName.FunctionCall.State

In this way, I would have a clear overview of my code.

Is this possible in Unity C#?

\$\endgroup\$
  • \$\begingroup\$ Is Fields a MonoBehaviour? How would one determine "the required function" using the game object's name? The more context you can give us about what gameplay feature you're implementing here, the better we can target answers that will be effective and scalable for that use. (Name-based lookups make me wary — there are almost always better solutions available) \$\endgroup\$ – DMGregory Aug 9 at 15:23
  • \$\begingroup\$ Yes, Fields is a MonoBehaviour. Calling the required function by his GameObject name would be very handy. In the case of fields, I'm just calling a "visible" toggle behavior, but I was hoping to find a clean structure in my code by just iterating thru referenced Empty children and accessing everything by GameObject names. Does this make sense? \$\endgroup\$ – karl Aug 9 at 16:05
  • \$\begingroup\$ It's not clear to me what operation you want to do with the name. Can you edit your question to describe the context in more detail, or possibly pseudocode demonstrating the kind of thing you want to do? \$\endgroup\$ – DMGregory Aug 9 at 16:06
  • \$\begingroup\$ I edited the question, this is the most simple scenario I can imagine. Please let me know if that is clearer now. Thanks! \$\endgroup\$ – karl Aug 9 at 16:22
  • \$\begingroup\$ Are you talking about GetComponent<Fields>()? \$\endgroup\$ – DMGregory Aug 9 at 16:28
1
\$\begingroup\$

This sets GameObjects' visibility by name by activating/deactivating them:

using System.Collections.Generic;
using UnityEngine;

public class Utility : MonoBehaviour
{
    static Dictionary<string, GameObject> gameObjects;

    public void Awake()
    {
        gameObjects = new Dictionary<string, GameObject>();
        foreach (var o in Resources.FindObjectsOfTypeAll<GameObject>())
            if (o.CompareTag("MyTag"))
                gameObjects.Add(o.name, o);
    }
    
    static public void SetVisible(string name, bool visibility = true)
    {
        gameObjects[name].SetActive(visibility);
    }
}

This makes the game object named "AnitaBath" visible by activating it

Utility.SetVisible("AnitaBath");

This makes the game object named "AnitaBath" invisible by deactivating it

Utility.SetVisible("AnitaBath", false);

How to Use This Script

This script should be added to a unique object in your scene like GameManager. It enumerates all objects in the scene tagged "MyTag" whenever it's Awake() method is called.

It assumes GameObject names are unique, you've created a new tag called "MyTag" and added this tag to the objects you'll be calling SetVisible on.

If you don't use the tag, you run the risk of affecting hidden internal objects (e.g., "SceneLight", "InternalIdentityTransform", "PreviewMaterials", "Cone", "Cube", ...)

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This works perfectly. Thank you so much!!! \$\endgroup\$ – karl Aug 11 at 11:55
2
\$\begingroup\$

This sets GameObjects' visibility by name by enabling/disabling their MeshRenderer:

static public class Utility
{
    static public void SetVisible(string name, bool visibility = true)
    {
        GameObject.Find(name).GetComponent<MeshRenderer>().enabled = visibility;
    }
}

This makes the game object named "AnitaBath" visible by activating it

Utility.SetVisible("AnitaBath");

This makes the game object named "AnitaBath" invisible by deactivating it

Utility.SetVisible("AnitaBath", false);

Assumptions

This script assumes the GameObjects you are working with are active and contain a MeshRenderer component

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks a lot, this is what I need. Will this work with inactive objects too? And I'm not sure how to use this. Do I have to make a Utility script and reference it from my GameHandler script? \$\endgroup\$ – karl Aug 10 at 11:15
  • \$\begingroup\$ Good point. GameObject.Find doesn't find inactive GameObjects. I updated the code to change visibility by enabling/disabling a MeshRenderer component instead. \$\endgroup\$ – Jim U Aug 10 at 19:06
  • \$\begingroup\$ Yes, you create a Utility.cs script. It should NOT be dragged onto a GameObject in your scene; it just needs to exist in your Project assets. \$\endgroup\$ – Jim U Aug 10 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.