如何在不导致 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)
当我遇到这个问题时,我已经开发了一段时间的 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)