【问题标题】:Why Unity don't see, that player are disabled?为什么 Unity 看不到,那个玩家被禁用了?
【发布时间】:2017-05-20 17:53:49
【问题描述】:

在 Unity3d 上的游戏中,我有一个带有 主摄像头 组件的 player 对象。我需要禁用播放器,然后使用另一个相机启用另一个对象,但我有 sctripts,它可以检测玩家是否在看某个对象(使用 raycast)。如果玩家的相机被禁用,我有错误。这就是我检查播放器是否启用的原因。但是由于某种原因,统一忽略了这个检查

   void Update ()
    {
        if (player == null)
            player = GameObject.FindGameObjectWithTag("Player");

        if (Input.GetButton("Fire1"))
            if (DoPlayerLookAtButton() && isAimationReadyToPlay)
                OpenCloseDoor();
    }

    bool DoPlayerLookAtButton()
    {
        if (player != null)
        {
            if (player.activeSelf) // why Unity don't see this string?
            {
                int layerMask = 1 << 9;
                layerMask = ~layerMask;

                RaycastHit _hit;
                // I have error here:
                Ray _ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
                bool isHit = Physics.Raycast(_ray, out _hit, 2.0f, layerMask);

                if (isHit && _hit.collider == thisCollider) return true;
                else return false;
            }
            else return false;
        }
        else return false;
    }

编辑 1

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    这里最重要的是要了解GameObject.FindGameObjectWithTagGameObject.Find 和其他FindXXX 的 GameObjects 函数不能将无法 能够找到 GameObjects在场景中不活跃的。

    这就是您收到该错误的原因。在大多数情况下,您有两种选择:

    1.从编辑器分配播放器:

    将播放器变量设为公共变量,然后从编辑器将播放器分配给播放器槽。

    public GameObject player;

    有了这个,你不需要再次使用GameObject.FindGameObjectWithTag,并且玩家不能为空,除非你明确地将它设置为null

    2。如果您的游戏对象必须在默认情况下处于非活动状态,则在编辑器中使其处于活动状态。

    StartAwake 函数的场景开始处使用GameObject.FindGameObjectWithTag 找到它,然后快速设置使其处于非活动状态 player.SetActive(false);.


    最后,Unity 默认支持查找非活动游戏对象,但以下是曾经可以用来查找它们的函数。不要因为它们很慢而滥用它们:

    按名称查找非活动游戏对象:

    GameObject FindObjectInActiveByName(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 FindObjectInActiveByTag(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 FindObjectInActiveByLayer(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;
    }
    

    编辑

    有了你的更多信息,问题出在Camera.main.ScreenPointToRay

    如果您的相机处于非活动状态或您的相机位于处于非活动状态的 GameObject 下,Camera.main 将返回 null。它将无法找到相机。当它返回 null 并且您尝试调用其 ScreenPointToRay 函数时,您会得到一个异常。

    此外,如果您在切换到的场景中有另一个摄像头,则必须确保将该摄像头的标签更改为“MainCamera”(如果这是您用于Raycast 的摄像头)。查看this 帖子以获取更多信息。你这样做是因为Camera.main 会寻找带有“MainCamera”标签的启用相机。

    【讨论】:

    • 谢谢!我了解,Unity 找不到非活动对象。我不明白,为什么它看不到条件if (player.activeSelf)?因为播放器对象被禁用,Unity 无论如何都会在这种情况下执行代码,但它不应该
    • 从您发布的屏幕截图中,您将获得NullReferenceException。不是在那一行代码(player.activeSelf)吗?
    • 糟糕,我的错。当您双击错误时,这就是Camera.main.ScreenPointToRay 的位置?此外,该错误是否与您的问题有关。我想我可能写了完全不同的东西......
    • 我现在明白了。在修改答案之前,我想确定问题出在哪里。请在 Unity 编辑器中双击错误,它将带您到代码中的错误位置。把那行代码贴在评论区
    • 不客气。如果没有那个截图,我们会认为问题出在player.activeSelf。编码愉快!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-30
    • 1970-01-01
    相关资源
    最近更新 更多