如何在不导致 Unity 溢出的情况下横向移动角色?

How to move a Character Sideways without causing any overflows in Unity?

当我遇到这个问题时,我已经开发了一段时间的 3D 无尽跑酷游戏。在横向移动期间,切换每条车道后,我的角色只是向后跳(-z 轴)几个小数点,这对于玩游戏的人来说非常明显;感觉他正在向后传送几位小数。添加此简单代码 transform.position = locationAfterChangingLane; 后问题出现了,该代码阻止了横向移动的溢出。它确实停止溢出,但产生了这个烦人的错误。

(代码行位于更新方法中的 isChangingLane if 语句中。)

这是我的脚本(完整的,我还在上面的代码行的地方做了注释,以便于参考。)

//Variables for Lane switching 
    private bool isChangingLane = false;
    private Vector3 locationAfterChanginLane = Vector3.zero;
    private Vector3 sideWayMovementDistance = Vector3.right * 2f; // This might be the case that triggers abnormal movements
    private float sideWaySpeed = 6f;

    public enum Lane
    {
        Left,
        Right,
        Center
    }

    public enum MoveDirection
    {
        Left,
        Right,
        None
    }

    Lane currentLane = Lane.Center;

     void Update()
    {
        currentBaseState = anim.GetCurrentAnimatorStateInfo(0);

        if (controller.isGrounded)
        {
            verticalVelocity = -0.5f;
            if (currentBaseState.fullPathHash == locoState)
            {
                if (Input.GetButtonDown("Jump"))
                {
                    verticalVelocity = 18f;

                    anim.SetBool("Jump", true);
                }
                else if (Input.GetKeyDown(KeyCode.S))
                {
                    anim.SetBool("Slide", true);
                }

            }

            MoveLeftRight(); // This is the method to move right and left.

            if (isChangingLane)
            {
                if (Math.Abs(transform.position.x - locationAfterChanginLane.x) < 0.1f)
                {
                    isChangingLane = false;
                    moveVector.x = 0;
                    transform.position = locationAfterChangingLane; // This is the code which throws this issue.
                }
            }



        }
    }

    private void MoveLeftRight()
    {

        MoveDirection requestedMoveDirection = MoveDirection.None;
        if (Input.GetKeyDown(KeyCode.A) && !isChangingLane)
        {
            requestedMoveDirection = MoveDirection.Left;
            isChangingLane = true;
        }
        else if (Input.GetKeyDown(KeyCode.D) && !isChangingLane)
        {
            requestedMoveDirection = MoveDirection.Right;
            isChangingLane = true;
        }

        switch (requestedMoveDirection)
        {
            case MoveDirection.Right:
                if (currentLane == Lane.Right)
                {
                    Debug.Log("Right Lane");
                    break; //Do nothing when in right lane.

                }
                else if (currentLane == Lane.Center)
                {
                    locationAfterChanginLane = transform.position + sideWayMovementDistance;
                    moveVector.x = +sideWaySpeed;

                    currentLane = Lane.Right;
                    Debug.Log("Center --> Right");
                }
                else if (currentLane == Lane.Left)
                {
                    locationAfterChanginLane = transform.position + sideWayMovementDistance;
                    moveVector.x = +sideWaySpeed;

                    currentLane = Lane.Center;
                    Debug.Log("Left --> Center");
                }
                break;
            case MoveDirection.Left:
                if (currentLane == Lane.Left)
                {
                    Debug.Log("Left Lane");
                    break; //Do nothing when in left lane.
                }
                else if (currentLane == Lane.Center)
                {
                    locationAfterChanginLane = transform.position - sideWayMovementDistance;
                    moveVector.x = -sideWaySpeed;

                    currentLane = Lane.Left;

                    Debug.Log("Center --> Left");
                }
                else if (currentLane == Lane.Right)
                {
                    locationAfterChanginLane = transform.position - sideWayMovementDistance;
                    moveVector.x = -sideWaySpeed;

                    currentLane = Lane.Center;

                    Debug.Log("Right --> Center");
                }
                break;
        }
    }

将不胜感激。我该如何解决这个问题?您还可以解释一下为什么会这样吗?非常感谢!

当你的角色改变车道时,你似乎有一个非瞬时的移动动画。这很好,但看起来你在有人向左或向右按​​的那一刻保存了目的地点。这个位置存储在内存中,然后大约 0.5 秒后,当他们完全到达那条车道时,它会重新使用那个位置——一直留在他们身后。

一个快速的解决方法是,一旦车道移动动画结束,只需更改 locationAfterChangingLane 的 Z 分量以匹配玩家当前的 Z 分量。或者,不保存和设置该向量,而是对玩家的位置应用 Math.Max/Math.Min 运算,这样他们就不会超过某个最大值。

另一个旁注:我看到一些人 运行 在玩他们的无限 运行ner 超过几分钟时陷入数学问题,因为他们的所有数字都进入了高范围。有可能你想要考虑简单地让世界的某些部分 "slide past" 成为一个静止的主角并在他身后循环,这样即使在玩了 20 分钟后他仍然在 (0, 0, 0)