【问题标题】:Raycast returns null for no apparent reasonRaycast 无缘无故返回 null
【发布时间】:2019-02-25 14:05:50
【问题描述】:

好的,这么快的问题,我做了一个简单的:

Ray ray;

然后在update()中我做了一个简单的:

ray = Camera.current.ScreenPointToRay(Input.mousePosition);
Debug.Log(Camera.current.ScreenPointToRay(Input.mousePosition));

由于某种原因,在控制台中,debug.log 注册了一个正在投射的射线,而射线只是认为它是空的。

有什么想法吗?

这是 debug.log 输出:

原点:(-0.2, 2.5, 14.8),方向:(-0.4, 0.5, -0.7)
Unity.engine.Debug:Log(Object)
TankController:Update()(在 Assets/Games/Chisana/Scripts/TankController.cs:136)

这是光线输出:

NullReferenceException:对象引用未设置为对象的实例
TankController.Update()(在 Assets/Games/Chisana/Scripts/TankController.cs:135)

如果我忽略了什么,这里是完整的脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TankController : MonoBehaviour
{
    Vector3 targetPosition;
    Vector3 lookAtTarget;

    public Vector4 selectedColor;
    public Vector4 deselectedColor;

    Quaternion playerRot;

    public float rotSpeed = 2;
    public float speed = 3;

    bool OneExecution = false;
    int count = 0;

    public bool Moving = false;
    public bool Selected = false;
    public bool UiSelected = false;
    public bool Hovering = false;

    public GameObject UI;
    public BoxCollider HitBox;

    public DoEverything Properties;
    public GameObject childObj;

    public MeshRenderer mrHighlight;

    public PlayerMaster playerMaster;
    int playerMasterTeam;

    SkinnedMeshRenderer[] skinnedMeshRenderersScan;
    public List<SkinnedMeshRenderer> skinnedMeshRenderersList = new List<SkinnedMeshRenderer>();

    Ray ray;
    RaycastHit hit;

    void Start()
    {
        Properties = GetComponentInChildren<DoEverything>(); //Get the DoEverything script

        childObj = Properties.InstancedEntity; //Get the object it will spawn

        if (mrHighlight.enabled != false && mrHighlight != null) //Make sure the highlight isn't enabled and not null
        {
            mrHighlight.enabled = false;
        }

        skinnedMeshRenderersScan = childObj.GetComponentsInChildren<SkinnedMeshRenderer>(); //Looks for all skinned mesh renderers in child object

        foreach (SkinnedMeshRenderer element in skinnedMeshRenderersScan) //For every object it finds
        {
            if (!skinnedMeshRenderersList.Contains(element)) //If it isn't already in this list
            {
                skinnedMeshRenderersList.Add(element); //Add to the list
            }
        }

        playerMasterTeam = playerMaster.Team;
    }

    void LClickRay()
    {

    }

    void RClickRay()
    {

    }

    void OnMouseEnter()
    {
        Hovering = true;
        foreach (SkinnedMeshRenderer element in skinnedMeshRenderersScan) //For every object it finds
        {
            element.material.color = selectedColor;
        }
    }

    void OnMouseExit()
    {
        Hovering = false;
        foreach (SkinnedMeshRenderer element in skinnedMeshRenderersScan) //For every object it finds
        {
            element.material.color = deselectedColor;
        }
    }

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            Physics.IgnoreCollision(collision.collider, HitBox);
        }
    }

    void Move()
    {
        transform.rotation = Quaternion.Slerp(transform.rotation,
                                                    playerRot,
                                                    rotSpeed * Time.deltaTime);
        transform.position = Vector3.MoveTowards(transform.position,
                                                targetPosition,
                                                speed * Time.deltaTime);

        if (transform.position == targetPosition)
        {
            Moving = false;
        }
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            LClickRay();
        }
        if (Input.GetMouseButtonDown(1))
        {
            RClickRay();
        }

        if (Moving == true)
        {
            Move();
        }

        ray = Camera.current.ScreenPointToRay(Input.mousePosition);
        Debug.Log(Camera.current.ScreenPointToRay(Input.mousePosition));
    }
}

【问题讨论】:

  • ray = Camera.current.ScreenPointToRay(Input.mousePosition);
  • 嗯,是的,Debug 和 ray 是单独的代码行。唯一的区别是调试调用它并在控制台中显示它是什么。当 ray 调用它并将其存储在一个名为 ray 的 Ray 变量中时。
  • 麻烦的是,当debug调用它时,它检测到它没有问题。当我尝试将它存储在一个变量中时,它只是假装它为空。
  • 请不要将输出添加为图像,而是添加为原始文本并将其格式化为输出(前缀&gt;

标签: c# unity3d


【解决方案1】:

不要使用Camera.current

来自API

我们当前渲染的相机,仅用于低级渲染控制(只读)。

大多数情况下,您会想改用Camera.main在实现以下事件之一时使用此函数:MonoBehaviour.OnRenderImageMonoBehaviour.OnPreRenderMonoBehaviour.OnPostRender


所以改用Camera.main

第一个启用的相机标记为“MainCamera”(只读)。

另请注意

场景中的主要相机。如果场景中没有这样的相机,则返回 null。此属性在内部使用FindGameObjectsWithTag,并且不缓存结果。如果每帧使用多次,建议缓存Camera.main的返回值。

所以请确保相机被标记为MainScene, aktive 并且你应该只使用它一次来获取参考并重复使用它

private Camera _mainCamera;

private void Awake ()
{
    _mainCamera = Camera.main;

    //Maybe a check
    if(!_mainCamera)
    {
        Debug.LogError("No MainCamera in Scene!");
        enabled = false;
    }
}

void Update()
{
    // ...

    ray = _mainCamera.ScreenPointToRay(Input.mousePosition);
    Debug.Log(ray);
}

【讨论】:

  • 我刚刚将 current 更改为 main,它工作得很好,但如果不是太麻烦,你会不会碰巧知道在多人游戏的情况下你会如何做到这一点?
  • 什么意思?在“多人游戏情况”中,仍然应该只有一个活跃的 MainCamera,对吗?还是您的意思是共享屏幕?
  • 就像,每个玩家都应该有自己的观点。
  • 我的问题是:它是共享屏幕吗?您想在同一台设备上显示两个摄像头视角吗?
  • 不,是在线多人游戏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-13
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
  • 2017-04-11
  • 1970-01-01
相关资源
最近更新 更多