你的问题不是很清楚。移动smoothly 可能意味着很多事情。
一般而言,您应该使用RigidBody.MovePosition 和Rigidbody.MoveRotation 来设置Rigidbody 的变换而不是rb.rotation 和rb.position,以便获得“平滑”的运动:
使用 Rigidbody.MovePosition 移动刚体,符合刚体的插值设置。
如果在刚体上启用刚体插值,则调用 Rigidbody.MovePosition 会导致任何中间帧中两个位置之间的平滑过渡。如果您想在每个 FixedUpdate 中连续移动刚体,则应使用此选项。
如果您想将刚体从一个位置传送到另一个位置,而不渲染中间位置,请改为设置 Rigidbody.position。
因此,您可以看到,根据您的设置,使用 Rigidbody.MovePosition 可能已经导致“平稳”移动。
rb.MovePosition(transform.position + Vector3.up * 2.0f);
你也使用Input.GetKeyDown,所以它像触发器一样工作......它不像Input.GetKey那样被连续调用
如果您想在按住键的同时连续移动,请使用例如
// set e.g. in the inspector
public float verticalMoveSpeed;
// ...
if (Input.GetKey(KeyCode.UpArrow))
{
rb.MovePosition(transform.position + Vector3.up * verticalMoveSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.DownArrow))
{
rb.MovePosition(transform.position - Vector3.up * verticalMoveSpeed * Time.deltaTime);
}
如果您只想使用GetKeyDown 触发移动,您也可以执行类似的操作,例如
// set e.g. in the inspector
public float verticalMoveSpeed;
// ...
if (Input.GetKeyDown(KeyCode.UpArrow))
{
StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed));
}
else if (Input.GetKeyDown(KeyCode.DownArrow))
{
StartCoroutine(MoveVertical(-2.0f, verticalMoveSpeed));
}
// ...
private IEnumerator MoveVertical(float distance, float speed)
{
var originalY = transform.position.y;
var targetY = originalY + distance;
var currentY = originalY;
do
{
rb.MovePosition(new Vector 3(transform.position.x, currentY, transform.positiom.z);
// Update currentY to the next Y position
currentY = Mathf.Clamp(currentY + speed * Time.deltaTime, originalY, targetY);
yield return null;
}
while(currentY < originalY);
// make sure you didn't move to much on Y
rb.MovePosition(new Vector3(transform.position.x, targetY, transform.position,z));
}
还有两个选项可以防止并发例程:
-
使用标志。这也可以防止例程被中断/调用两次/调用并发
privtae bool isMovingVertical;
// ...
if (Input.GetKeyDown(KeyCode.UpArrow) && !isMovingVertical )
{
StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed));
}
else if (Input.GetKeyDown(KeyCode.DownArrow) && !isMovingVertical )
{
StartCoroutine(MoveVertical(-2.0f, verticalMoveSpeed));
}
// ...
private IEnumerator MoveVertical(float distance, float speed)
{
isMovingVertical = true;
// ...
isMovingVertical = false;
}
-
使用StopAllCoroutines 中断正在运行的例程(注意,这可能会导致向一个方向“无限”移动 - 至少在您没有通过额外检查阻止它的情况下)
if (Input.GetKeyDown(KeyCode.UpArrow))
{
StopAllCoroutines();
StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed));
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
StopAllCoroutines();
StartCoroutine(MoveVertical(-2.0f, verticalMoveSpeed));
}