繁体   English   中英

按名称、标签或层查找非活动游戏对象

[英]Find inactive GameObject by name, tag or layer

首先,我需要停用一个游戏对象,然后在 10 秒后激活它,所以我认为协程是合适的:

IEnumerator BarDeactivate(float sec)
{
        yield return new WaitForSeconds(sec);

        var obj = GameObject.Find("OBJ");
        obj.SetActive(false);
}

IEnumerator BarReactivate(float sec)
{
        yield return new WaitForSeconds(sec);

        var obj = transform.Find("OBJ");
        obj.SetActive(true);
}

显然,我不能再使用GameObject.Find所以我使用transform.Find来查找不活动的游戏对象,但当然.SetActive现在不起作用,因为 obj 实际上不是游戏对象......

如何转换找到的变换,以便可以再次将其设置为活动状态?

我尝试obj.gameObject.SetActive(true)但它一定是错误的,因为对象不会恢复生机......

问题是 Unity 找不到非活动的游戏对象。 GameObject.Find只会找到活动的 GameObject。 您应该找到 GameObject 并将其存储在全局变量中,或者将变量设为 public,然后从编辑器中分配它。

我的解决方案使用全局变量,然后将 GameObject 存储在初学者中,这样您就不必再次查找它。

GameObject obj;

void Start()
{
    obj = GameObject.Find("OBJ");
}
IEnumerator BarDeactivate(float sec)
{
    yield return new WaitForSeconds(sec);
    obj.SetActive(false);
}

IEnumerator BarReactivate(float sec)
{
    yield return new WaitForSeconds(sec);
    obj.SetActive(true);
}

下面是我制作的一个包装器,它通过名称、标签或层来查找游戏对象,即使它们处于非活动状态。

你不应该在每一帧都使用这些,因为它们很慢。 如果在StartAwake功能中使用它们是很好的。

找到一个游戏对象:

用法:

void Start()
{
    GameObject objByName = FindInActiveObjectByName("Cube");
    GameObject objByTag = FindInActiveObjectByTag("CubeTag");
    GameObject objByLayer = FindInActiveObjectByLayer(LayerMask.NameToLayer("CubeLayer"));
}

按名称查找处于活动状态的游戏对象:

GameObject FindInActiveObjectByName(string name)
{
    Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
    for (int i = 0; i < objs.Length; i++)
    {
        if (objs[i].hideFlags == HideFlags.None)
        {
            if (objs[i].name == name)
            {
                return objs[i].gameObject;
            }
        }
    }
    return null;
}

按标签查找处于活动状态的游戏对象:

GameObject FindInActiveObjectByTag(string tag)
{

    Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
    for (int i = 0; i < objs.Length; i++)
    {
        if (objs[i].hideFlags == HideFlags.None)
        {
            if (objs[i].CompareTag(tag))
            {
                return objs[i].gameObject;
            }
        }
    }
    return null;
}

按层查找处于活动状态的游戏对象:

GameObject FindInActiveObjectByLayer(int layer)
{

    Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
    for (int i = 0; i < objs.Length; i++)
    {
        if (objs[i].hideFlags == HideFlags.None)
        {
            if (objs[i].gameObject.layer == layer)
            {
                return objs[i].gameObject;
            }
        }
    }
    return null;
}


查找所有游戏对象(注意下面所有函数名称中对象中的“s” ):

用法:

void Start()
{
    GameObject[] objByNames = FindInActiveObjectsByName("Cube");
    GameObject[] objByTags = FindInActiveObjectsByTag("CubeTag");
    GameObject[] objByLayers = FindInActiveObjectsByLayer(LayerMask.NameToLayer("CubeLayer"));
}

按名称查找处于活动状态的 GameObject[s]:

GameObject[] FindInActiveObjectsByName(string name)
{
    List<GameObject> validTransforms = new List<GameObject>();
    Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
    for (int i = 0; i < objs.Length; i++)
    {
        if (objs[i].hideFlags == HideFlags.None)
        {
            if (objs[i].gameObject.name == name)
            {
                validTransforms.Add(objs[i].gameObject);
            }
        }
    }
    return validTransforms.ToArray();
}

按标签查找非活动的 GameObject[s]:

GameObject[] FindInActiveObjectsByTag(string tag)
{
    List<GameObject> validTransforms = new List<GameObject>();
    Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
    for (int i = 0; i < objs.Length; i++)
    {
        if (objs[i].hideFlags == HideFlags.None)
        {
            if (objs[i].gameObject.CompareTag(tag))
            {
                validTransforms.Add(objs[i].gameObject);
            }
        }
    }
    return validTransforms.ToArray();
}

按层查找处于活动状态的 GameObject[s]:

GameObject[] FindInActiveObjectsByLayer(int layer)
{
    List<GameObject> validTransforms = new List<GameObject>();
    Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
    for (int i = 0; i < objs.Length; i++)
    {
        if (objs[i].hideFlags == HideFlags.None)
        {
            if (objs[i].gameObject.layer == layer)
            {
                validTransforms.Add(objs[i].gameObject);
            }
        }
    }
    return validTransforms.ToArray();
}

在您的情况下, 调用是比协程更好的选择。 此外,据我所知,您不能 .Find 一个非活动对象,因此您应该将找到的对象分配给一个字段。

var obj;

void BarDeactivate(){
    obj = GameObject.Find("OBJ");
    obj.SetActive(false);
}

void BarReactivate(){
    obj.SetActive(true);
}

通过 Invoke 调用它们,如下所示:

Invoke("BarDeactivate", sec);
Invoke("BarReactivate", sec);

我在 ARCore、Vuforia 等方面遇到了这个问题,因为游戏对象在被跟踪之前是不存在的。 一种方法是等待目标被识别,然后寻找游戏对象,但如果它们手动不活动,唯一的另一种(简单?)方法是手动列出它们并将它们作为公共数组与脚本链接。 如果您的脚本已链接,那么即使是非活动的游戏对象也可以访问。

您可以通过代码找到gameobject并在运行时在检查器中分配:

1-在你必须得到的游戏对象上附加脚本。 eg i have attach " PoliceCarController ";

2 -编写代码

void Start()
{ 
 GameObject PoliceCar = GameObject.FindObjectOfType<PoliceCarController>(true).gameObject;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM