按名称,标签或图层查找非活动的GameObject

时间:2017-06-09 11:02:44

标签: c# unity3d

首先,我需要停用游戏对象,然后在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),但一定是错的,因为对象不会复活......

3 个答案:

答案 0 :(得分:8)

问题是Unity无法找到不活动的GameObjects。 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函数中使用它们,它们就很好。

找一个GameObject:

<强> USAGE:

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

按名称查找不活跃的GameObject:

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:

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:

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

查找所有游戏对象(请注意以下所有功能名称中对象中的&#34; s&#34; ):

<强> USAGE:

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

通过Tag找到不活跃的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();
}

答案 1 :(得分:2)

在你的情况下,Invoke是一个比协程更好的选择。另外,据我所知你不能找到一个非活动对象,所以你应该将找到的对象分配给一个字段。

var obj;

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

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

通过Invoke这样调用它们:

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

答案 2 :(得分:-1)

我对ARCore,Vuforia等存在此问题,因为GameObject在被跟踪之前是不活跃的。一种方法是等待目标被识别,然后寻找GameObject,但是,如果它们是手动不活动的,则唯一(不复杂?)的另一种方法是手动列出它们并将它们链接为带有脚本的公共数组。如果您的脚本已链接,那么即使是无效的GameObject也将可以访问。