【问题标题】:Get distance between Player Object and Clicked Location using RayCast使用 RayCast 获取玩家对象和点击位置之间的距离
【发布时间】:2021-03-04 05:34:29
【问题描述】:

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

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

ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(ray.origin, ray.direction, out hitInfo);
var testDistance = Vector3.Distance(transform.position, ray.direction.normalized);

编辑:将 ray.direction.normalized 替换为 hitInfo.transform.position 具有相似的结果,该值远大于实际距离。

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

我得到以下值:

我知道我肯定错过了某种必须完成的转换或步骤。

更多细节可能会有所帮助?

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

【问题讨论】:

  • 相反,我所做的是在点击位置创建一个新对象来表示目的地并使用该对象来计算距离。我会让这个保持打开状态,但万一有人对此有答案,而其他人出于某种原因正在寻求做类似的事情。

标签: c# unity3d


【解决方案1】:

你的问题很简单:

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

当然这完全没有意义,因为它基本上等于Camera.main.transform.forward。如果你使用像位置这样的归一化方向,它基本上会是 Unity 原点周围距离为 1 的东西。而你的玩家可以定位在任何地方。你想检查玩家和hitInfo.point之间的距离!

// 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);
    }
}

在您的情况下,我将使用光线和 Playboard 的交点 - 假设 Unity XZ Plane

然后获取映射到 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 链接在代码 cmets 中。

【讨论】:

  • 啊,我明白了!我意识到,即使我尝试使用 hitInfo 而不是 ray.direction,我也没有删除 Y,也没有在任何给定时间得到“hitInfo.point”,我只是将 hitInfo Vector 扔到距离方法中.非常感谢您解释和链接 cmets 中的所有内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 2016-12-14
  • 1970-01-01
  • 2014-03-23
  • 2019-02-27
相关资源
最近更新 更多