在我在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;
}
答案 0 :(得分:1)
最重要的是要明白,游戏对象的GameObject.FindGameObjectWithTag
,GameObject.Find
和其他FindXXX
函数 >能够找到场景中不活跃的游戏对象。
这是您收到该错误的原因。在大多数情况下,您有两种选择:
1 。从编辑中分配玩家:
将播放器变量设为公共变量,然后将播放器分配给编辑器中的播放器插槽。
public GameObject player;
有了这个,您不需要再次使用GameObject.FindGameObjectWithTag
,除非您明确将其设置为null
,否则播放器不能为空。
2 。如果您的GameObject默认情况下必须处于非活动状态,请从编辑器中激活它。
在GameObject.FindGameObjectWithTag
或Start
函数的场景开始时使用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”标签的已启用相机。