为什么Unity看不到,那个玩家被禁用了?

时间:2017-05-20 07:54:25

标签: c# unity3d

在我在Unity3d上的游戏中,我有一个播放器对象,带有主摄像头组件。我需要禁用播放器然后用另一个相机启用另一个对象,但我有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;
    }

enter image description here

修改1 enter image description here

1 个答案:

答案 0 :(得分:1)

最重要的是要明白,游戏对象GameObject.FindGameObjectWithTagGameObject.Find和其他FindXXX函数 >能够找到场景中不活跃的游戏对象。

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

1 。从编辑中分配玩家:

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

public GameObject player;

有了这个,您不需要再次使用GameObject.FindGameObjectWithTag,除非您明确将其设置为null,否则播放器不能为空。

2 。如果您的GameObject默认情况下必须处于非活动状态,请从编辑器中激活它。

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

最后,Unity 不支持支持在默认情况下查找非活动GameObjects,但以下是可用于查找它们的函数。不要滥用它们,因为它们很慢:

按名称查找不活跃的GameObject:

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:

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:

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”标签的已启用相机。