如何在所有对象上搜索特定的脚本名称并对其执行某些操作?

时间:2017-12-15 20:37:35

标签: c# unity3d unity5

我在Hierarchy中有一个GameObject作为父级。 我想循环遍历所有子游戏对象的脚本名称:

ItemInformation

然后我想检查带有脚本的GameObjects字段TextArea是用文本填充而不是空字符串。

然后那些非空的,与我点击的对象的名称进行比较,然后获取与该游戏对象相关的信息和信息。

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

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

这是我想要遍历孩子的脚本,并与我点击它的名字进行比较:

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;
    }
}

例如,让我说移动相机,看着一扇门。 让我们说门GameObject的名字是:SmallDoor

现在在这一部分:

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);
            }
        }

我想循环访问父GameObject下的子节点检查哪些对象附加了脚本ItemInformation,获取对象名称将其与我单击的对象名称(例如SmallDoor)进行比较并显示信息(iteminformation.description)小门

2 个答案:

答案 0 :(得分:4)

如果您尝试检索的对象被childed到父GameObject,那么您只需执行以下操作就可以遍历父项的子项:

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

如果他们没有与父游戏对象联系,你可以为他们分配所有共同的“标签”,然后将它们全部解决,然后迭代它们并做同样的事情。

另外,您应该在问题的标题中指明这是Unity特定的。

答案 1 :(得分:4)

CAVEAT:在某些情况下,您可能不希望将Linq用于性能或兼容性(iOS)问题。阅读this discussion

中的更多内容

如果你喜欢生活在边缘[参考上面的CAVEAT],你也可以使用Linq(注意这需要在脚本顶部使用指令)

using System.Linq

现在你可以做各种有趣的事情,如:

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);
}