【问题标题】:When I make an object face a mouse cursor in Unity it eventually offsets当我在 Unity 中使对象面对鼠标光标时,它最终会偏移
【发布时间】:2020-08-13 01:59:46
【问题描述】:

我制作了一个让玩家指向鼠标光标的脚本,但最近我发现了一个错误。当我将鼠标光标移动太多时(例如,当我将鼠标绕着对象旋转时,会导致对象四处移动。),对象最终会指向鼠标应该在的位置。例如,光标会向对象发出信号以查看它,并且对象最终看起来有点偏离,在快速操纵后感觉很奇怪。我怎样才能使对象始终面对光标,没有偏移,即使我尽可能地移动光标。

            private void LateUpdate()
{
    Vector3 lookAtPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    Vector3 mousePoint = new Vector3(lookAtPoint.x, lookAtPoint.y, 0);

    float angle = getAngle(transform.position, mousePoint);
    transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(0, 0, angle), 9f * Time.deltaTime);

    float getAngle(Vector3 currentLocation, Vector3 mouseLocation)
    {
        float x = mouseLocation.x - currentLocation.x;
        float y = mouseLocation.y - currentLocation.y;

        return angle = Mathf.Rad2Deg * Mathf.Atan2(y, x);

    }
}

【问题讨论】:

    标签: c# unity3d game-physics


    【解决方案1】:

    看起来这取决于您使用 Quaternion.Lerp() 的方式。特别是最后一个参数 - 它是您提供的介于 0f 和 1f 之间的值,它不会为您自动递增。

    所以要解决这个问题,你要做的就是在某个地方保存一个浮点数。当您移动鼠标时(鼠标位置自上一帧以来已更改),然后再次从 0f 开始该值。然后每帧以某个值递增,直到等于或大于 1f。

    这样做不仅可以修复您的错误。它将根据您的增量速度为您提供平滑的旋转效果。下面是一个例子。

    internal class SomeClass : MonoBehaviour
    {
      private float lerpAmount = 0f;
      private Vector3 cachedMousePosition = Vector3.zero;
      
      private void LateUpdate()
      {
        var mousePosition
          = Camera.main.ScreenToWorldPoint(Input.mousePosition)
          * new Vector3(1, 1, 0);
        
        bool recalculateRotation = false;
        if (this.cachedMousePosition != mousePosition)
        {
          this.lerpAmount = 0f;
          recalculateRotation = true;
        }
    
        if (this.lerpAmount < 1f)
        {
          this.lerpAmount = Mathf.Min(this.lerpAmount + Time.deltaTime, 1f);
          recalculateRotation = true;
        }
    
        if (recalculateRotation)
        {
          float angle = getAngle(transform.position, mousePoint);
          transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(0, 0, angle), this.lerpAmount);
        }
    
        float getAngle(Vector3 currentLocation, Vector3 mouseLocation)
        {
          float x = mouseLocation.x - currentLocation.x;
          float y = mouseLocation.y - currentLocation.y;
    
          return angle = Mathf.Rad2Deg * Mathf.Atan2(y, x);
    
        }
      }
    

    【讨论】:

    • 我尝试实现这一点并取得了一定的成功。它似乎使虫子消失了,但它被非常波涛汹涌的运动所取代,以至于它在移动时随机冻结。这是我的代码void Update() { Vector3 mouseDelta = Input.mousePosition - lastMouseCoordinate; lastMouseCoordinate = Input.mousePosition; if(Mathf.Abs(mouseDelta.x + mouseDelta.y) &gt; 0) { mouseMovementDetection = 0; } else { while(mouseMovementDetection &lt;= 10) { mouseMovementDetection += 0.1f; } }
    • 我在答案中添加了一个代码示例。我没有测试它,我只是写得很快,所以你可能需要做一些调试。
    • 好像有些是用Java写的。你能帮我把它全部放在c#中吗?我还在Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition) * new Vector3(1, 1, 0); 收到一个错误,说您不能将“*”与vector3 和vector2 一起使用。
    • var 是 C# 的新手。 docs.microsoft.com/en-us/dotnet/csharp/language-reference/… 没错,我忘记了 Multiply 不适用于 Unity 中的 Vectors。您可以改为在创建该变量后执行mousePosition.z = 0f;。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 2011-05-10
    相关资源
    最近更新 更多