Daniel Lip
Daniel Lip

Reputation: 11321

How can I search for specific script name on all objects and do something with it?

I have a GameObject in the Hierarchy as parent. I want to loop over all the child gameobjects for the script name:

ItemInformation

Then I want to check what GameObjects with the script the field TextArea is filled with text and not empty string.

Then those that are not empty to compare with the name of the object that I was clicking on and the then to get the information that is relative to this gameobject with the information.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemInformation : MonoBehaviour
{
    [TextArea]
    public string description;
}

This is the script where I want to loop over the children and to compare to what I clicked on by it's name:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DetectInteractable : MonoBehaviour
{
    public Camera cam;
    public float distanceToSee;
    public string objectHit;
    public Image image;
    public bool interactableObject = false;
    public Canvas canvas;
    public Text interactableText;
    public ItemInformation iteminformation;

    private RaycastHit whatObjectHit;
    private RotateObject rotateobj;
    private bool hasDescription = false;
    private bool clickForDescription = false;
    private int layerMask = 1 << 8;

    private void Start()
    {
        rotateobj = GetComponent<RotateObject>();
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            clickForDescription = true;
        }

        Debug.DrawRay(cam.transform.position, cam.transform.forward * distanceToSee, Color.magenta);

        if (rotateobj.rotating == false)
        {
            if (Physics.Raycast(cam.transform.position, cam.transform.forward, out whatObjectHit, distanceToSee, layerMask))
            {
                image.color = Color.red;
                objectHit = whatObjectHit.collider.gameObject.name;
                interactableObject = true;
                interactableText.gameObject.SetActive(true);
                interactableText.text = whatObjectHit.collider.gameObject.name;
                print("Hit ! " + whatObjectHit.collider.gameObject.name);
                hasDescription = true;
            }
            else
            {
                image.color = Color.clear;
                image.color = Color.white;
                interactableText.gameObject.SetActive(false);
                hasDescription = false;
                clickForDescription = false;
                print("Not Hit !");
            }
        }
    }

    private void OnGUI()
    {
        if (hasDescription == true && clickForDescription == true)
        {
            var centeredStyle = GUI.skin.GetStyle("Label");
            centeredStyle.alignment = TextAnchor.UpperCenter;
            GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 25, 100, 50), iteminformation.description, centeredStyle);
        }
    }

    public class ViewableObject : MonoBehaviour
    {
        public string displayText;
        public bool isInteractable;
    }
}

For example let's say I move the camera and looked over a door. And let's say the door GameObject name is: SmallDoor

Now in this part:

private void OnGUI()
        {
            if (hasDescription == true && clickForDescription == true)
            {
                var centeredStyle = GUI.skin.GetStyle("Label");
                centeredStyle.alignment = TextAnchor.UpperCenter;
                GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 25, 100, 50), iteminformation.description, centeredStyle);
            }
        }

I want to loop over the children under the parent GameObject check which objects have the script ItemInformation attached to it get the objects names compare it to the object name I clicked on for example SmallDoor and display the informat(iteminformation.description) for the SmallDoor

Upvotes: 2

Views: 372

Answers (2)

Rick Riensche
Rick Riensche

Reputation: 1099

CAVEAT: There may be cases where you do not want to use Linq for performance or compatibility (iOS) issues. Read more in this discussion

If you like living on the edge [ref CAVEAT above], you can also use Linq (Note this requires using directive at top of script)

using System.Linq

Now you can do all manner of fun things like:

var testName = "MyTargetObject";

// If you want to find ALL matching children:
var childInfos = gameObject.GetComponentsInChildren<ItemInformation>()
                               .Where(child => child.name == testName);

foreach (var itemInfo in childInfos)
{
    // do something with itemInfo.description
    print(itemInfo.description);            
}

// OR if you only want the first one to be found if there happen to be more than one..
var singleItemInfo = gameObject.GetComponentsInChildren<ItemInformation>()
                                  .Where(child => child.name == testName)
                                  .FirstOrDefault();

if (singleItemInfo != null)
{
    // do something with singleItemInfo.description
    print(singleItemInfo.description);
}

Upvotes: 4

Brandon Miller
Brandon Miller

Reputation: 1584

If the objects you're trying to retrieve are childed to a parent GameObject then you can loop over the children of the parent by simply doing:

foreach(GameObject child in parent)
{
    if(child.GetComponent<ItemInformation>() != null)
    {
       //do something
    }
}

If they are not childed to a parent gameobject you can assign them all a common "tag" and get them all that way, then iterate over them and do the same.

Also, you should specify in the title of your question that this is Unity specific.

Upvotes: 4

Related Questions