Ваш вопрос не совсем понятен.Перемещение smoothly
может означать много вещей.
В общем случае вы должны использовать RigidBody.MovePosition и Rigidbody.MoveRotation , чтобы установить преобразования Rigidbody
вместоrb.rotation
и rb.position
для получения «плавных» движений:
Используйте Rigidbody.MovePosition для перемещения Rigidbody, в соответствии с настройкой интерполяции Rigidbody.
Если интерполяция Rigidbodyвключается на Rigidbody, вызывая 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));
}