Есть несколько способов.Я бы не использовал Translate
, поскольку это дает вам небольшой контроль, а, например, MoveTowards
, который гарантирует, что у вас нет перестрелки в конце.Используйте это для линейного движения с заданной moveSpeed :
// set move speed in Units/seconds in the Inspector
public float moveSpeed = 1f;
private Vector3 desiredPos;
private bool isMoving;
private void Update()
{
if (!isMoving && Input.GetMouseButtonDown(0))
{
desiredPos = transform.position + Vector3.right * 1.5f;
isMoving = true;
}
if (!isMoving && Input.GetMouseButtonDown(1))
{
desiredPos = transform.position - Vector3.right * 1.5f;
isMoving = true;
}
if(isMoving)
{
transform.position = Vector3.MoveTowards(transform.position, desiredPos, moveSpeed * Time.deltaTime);
// this == is true if the difference between both
// vectors is smaller than 0.00001
if(transform.position == desiredPos)
{
isMoving = false;
// So in order to eliminate any remaining difference
// make sure to set it to the correct target position
transform.position = desiredPos;
}
}
}
Или, как вы просили, используйте Vector3.Lerp
, например,
// a factor between 0 and 1
[Range(0, 1)] public float lerpFactor;
...
transform.position = Vector3.Lerp(transform.position, desiredPos, lerpFactor);
lerpFactor
должно быть значением от 0
до 1
, где в нашем случае 0
означает, что объект никогда не перемещается, а 1
напрямую переходит на целевую позицию.Другими словами, чем ближе вы установите его на 0
, тем медленнее он достигнет цели, чем ближе вы установите на 1
, тем быстрее он достигнет цели.
многие люди делают это дляполучить "плавные" движения, но на самом деле происходит, например, если вы установите 0.5
для lerpFactor
, то каждый кадр, в котором объект находится посередине между текущей позицией и целевой позицией.
Это выглядит как-то плавно, движетсяочень быстрый в начале и очень очень медленный в конце ... но: на самом деле он никогда не достигает целевой позиции, а просто становится очень медленным.
Для вашего случая это хорошо, так как в любом случае мы сравниваем ток ицелевое положение с использованием ==
с точностью до 0.00001
.Нужно просто иметь в виду, как работает Lerp
.
Но при этом вы не будете иметь никакого контроля ни над скоростью перемещения, ни над продолжительностью.
Если вы хотите в целом больше контроля (как и я) Я бы порекомендовал использовать Coroutine (он не является абсолютно необходимым, и вы могли бы сделать то же самое в Update
, но на мой взгляд, сопрограммы лучше поддерживать и отслеживать).
Чем вы могли бы также сделать плавное ускорение и замедление с постоянной фиксированной продолжительностью независимо от того, как далеко расстояние
// set desired move duration in seconds
public float moveDuration = 1;
private bool isMoving;
privtae void Update()
{
if (!isMoving && Input.GetMouseButtonDown(0))
{
StartCoroutine(transform.position + Vector3.right * 1.5f, moveDuration);
}
if (!isMoving && Input.GetMouseButtonDown(1))
{
StartCoroutine(transform.position - Vector3.right * 1.5f, moveDuration);
}
}
private IEnumerator Move(Vector3 targetPosition, float duration)
{
if(isMoving) yield break;
isMoving = true;
var startPosition = transform.position;
var passedTime = 0f;
do
{
// This would move the object with a linear speed
var lerpfactor = passedTime / duration;
// This is a cool trick to simply ease-in and ease-out
// the move speed
var smoothLerpfactor = Mathf.SmoothStep(0, 1, lerpfactor);
transform.position = Vector3.Lerp(startPosition, targetPosition, smoothLerpfactor);
// increase the passedTime by the time
// that passed since the last frame
passedTime += Time.deltaTime;
// Return to the main thread, render this frame and go on
// from here in the next frame
yield return null;
} while (passedTime < duration);
// just like before set the target position just to avoid any
// under shooting
transform.position = targetPosition;
isMoving = false;
}
, и вы могли быпродолжайте расширять этот пример, чтобы использовать dtsnace для учета, например,
var actualDuration = duration * Vector3.Distance(startPosition, targetPosition);
, а затем повсеместно использовать actualDuration
.