C# 使用光线投射获取播放器对象和单击位置之间的距离

C# 使用光线投射获取播放器对象和单击位置之间的距离,c#,unity3d,C#,Unity3d,我的Unity3D项目有问题。我目前正在做一个等距游戏,我无法找到一种方法来计算玩家对象和我单击的位置之间的精确距离 下面是我的代码,它获取单击的位置,并计算播放器对象与单击位置之间的距离 ray = Camera.main.ScreenPointToRay(Input.mousePosition); Physics.Raycast(ray.origin, ray.direction, out hitInfo); var testDistance = Vector3.Distance(trans

我的Unity3D项目有问题。我目前正在做一个等距游戏,我无法找到一种方法来计算玩家对象和我单击的位置之间的精确距离

下面是我的代码,它获取单击的位置,并计算播放器对象与单击位置之间的距离

ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(ray.origin, ray.direction, out hitInfo);
var testDistance = Vector3.Distance(transform.position, ray.direction.normalized);
编辑:用hitInfo.transform.position替换光线.direction.normalized,结果类似,值远大于实际距离

然而,我有以下问题。 即使我在播放器模型下单击鼠标右键,testDistance变量也比我预期的要大得多

我得到以下值:

我知道我肯定错过了一些必须完成的转变或步骤

也许有更多的细节能帮上忙

  • 检查距离的脚本位于附加到播放器对象的更新()中
  • 摄影机未连接到播放机,它通过此脚本跟踪播放机对象:

    • 你的问题很简单:

      您正在检查玩家位置和光线方向之间的距离

      // If possible already reference this in the Inspector
      [SerializeField] private Camera _camera;
      
      private void Awake ()
      {
          // As fallback get the camera ONCE on runtime, "Camera.main" is expensive!
          //see https://docs.unity3d.com/ScriptReference/Camera-main.html
          if(!_camera) _camera = Camera.main;
      }
      
      private void Update()
      {
          var ray = _camera.ScreenPointToRay(Input.mousePosition);
          
          if(Physics.Raycast(ray, out hitInfo)
          {
              // Get the position where exactly you hit something
              var hitPoint = hitInfo.point;
              // Regardless of what we hit eliminate any difference in the Y axis 
              hitPoint.y = 0;
      
              // also map the player position on the XZ plane (erase any Y axis height)          
              var playerPosition = transform.position;
              playerPosition.y = 0;
      
              // Now you get the correct distance between both points in the XZ plane
              var distance = Vector3.Distance(hitPoint, playerPosition);       
              Debug.Log($"Distance: {distance}", this);
          }
      }
      
      当然,这毫无意义,因为它基本上等于Camera.main.transform.forward。如果你使用一个标准化的方向,比如一个位置,它基本上是围绕单位原点的,距离为1。而你的玩家可以被安置在任何地方。您想检查玩家和之间的距离

      // If possible already reference this in the Inspector
      [SerializeField] private Camera _camera;
      
      private void Awake ()
      {
          // As fallback get the camera ONCE on runtime, "Camera.main" is expensive!
          //see https://docs.unity3d.com/ScriptReference/Camera-main.html
          if(!_camera) _camera = Camera.main;
      }
      
      private void Update()
      {
          var ray = _camera.ScreenPointToRay(Input.mousePosition);
          
          if(Physics.Raycast(ray, out hitInfo)
          {
              // Get the position where exactly you hit something
              var hitPoint = hitInfo.point;
              // Regardless of what we hit eliminate any difference in the Y axis 
              hitPoint.y = 0;
      
              // also map the player position on the XZ plane (erase any Y axis height)          
              var playerPosition = transform.position;
              playerPosition.y = 0;
      
              // Now you get the correct distance between both points in the XZ plane
              var distance = Vector3.Distance(hitPoint, playerPosition);       
              Debug.Log($"Distance: {distance}", this);
          }
      }
      

      在你的例子中,我将使用光线和播放板的交点——假设单位为XZ

      然后获取映射到该XZ平面上的玩家位置与该XZ平面上的射线击中点之间的距离

      这样做的好处是,这是纯数学的,不需要任何对撞机,如果另一个对撞机挡住了路,它就不会断裂

      差不多

      // If possible already reference this in the Inspector
      [SerializeField] private Camera _camera;
      
      // First parameter is the global UP axis -> we get the flat floor in XZ axis
      // For the second parameter you could e.g. change the Y component if there needs
      // to be a ground height different to 0
      // see https://docs.unity3d.com/ScriptReference/Plane-ctor.html
      private Plane _xzPlane = new Plane(Vector3.up, Vector3.zero);
      
      private void Awake ()
      {
          // As fallback get the camera ONCE on runtime, "Camera.main" is expensive!
          //see https://docs.unity3d.com/ScriptReference/Camera-main.html
          if(!_camera) _camera = Camera.main;
      }
      
      private void Update()
      {
          var ray = _camera.ScreenPointToRay(Input.mousePosition);
          // Directly use a raycasts on the XZ plane -> pure mathematical doesn't need any collider/physics 
          // see https://docs.unity3d.com/ScriptReference/Plane.Raycast.html
          if(plane.Raycast(ray, out hitDistance)
          {
              // get the position where we hit the XZ plane
              // see https://docs.unity3d.com/ScriptReference/Ray.GetPoint.html
              var xzHitPoint = ray.GetPoint(hitDistance);
              // map the player position on the XZ plane (erase any Y axis height)
              // see https://docs.unity3d.com/ScriptReference/Plane.ClosestPointOnPlane.html
              var xzPlayerPosition = plane.ClosestPointOnPlane(transform.position);
              // Now you get the correct distance between both points in the XZ plane
              var distance = Vector3.Distance(xzHitPoint, xzPlayerPosition);       
              Debug.Log($"Distance: {distance}", this);
          }
      }
      

      API链接在代码注释中。

      我所做的是在单击位置创建一个新对象来表示目的地,并使用该对象来计算距离。不过,我会把这个留着,以防有人对此有答案,而其他人,无论出于什么原因,希望做类似的事情。啊,我明白了!我意识到,即使我尝试使用hitInfo而不是ray.direction,我也没有删除Y,也没有在任何给定时间获得“hitInfo.point”,我只是在距离方法中抛出hitInfo向量。非常感谢您解释并链接评论中的所有内容。