Во-первых, насколько я понимаю, вы только хотите сгладить значение X позиции, поэтому вы скорее сделаете
private IEnumerator Move_Routine(Transform transform, float from, float to)
{
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime;
// only lerp the single float value
var currentX = Mathf.SmoothStep(from, to, t);
// let the current other two values unchanged
transform.position.x = currentX;
yield return null;
}
// Just to be sure there is no under/overshooting I would
// always set the fixed value in the end
transform.position.x = to;
}
Однако другая проблема в вашем случае заключается в том, что вы имеете дело сRigidBody.
Вы не должны вообще использовать transform.position =
на твердых телах, а playerRigidbody.position =
или playerRigidbody.MovePosition(targetPosition)
Coroutine выполняется при каждом вызове Update
, но вы должны менять твердые тела только в FixedUpdate
=> вы можете использовать WaitForFixedUpdate
в своей сопрограмме
Третья проблема заключается в том, чтоВы можете запустить несколько сопрограмм одновременно, если снова нажать кнопку до завершения движения.=> Вы можете решить это просто с помощью флага bool.В качестве альтернативы, если вы хотите разрешить ввод (например, для движения в другом направлении, вы должны StopCoroutine
текущую процедуру сначала)
Следовательно, дрожание и т. Д. Итак, вместе:
private bool alreadyLerping;
private void FixedUpdate()
{
playerRigidbody.velocity = new Vector2(0.0f, 2.0f);
if (Input.GetKeyDown(KeyCode.RightArrow))
{
// only do if not lerping laready otherwise input is ignored
if (newBallPos != 2 && !alreadyLerping)
{
var currentX = transform.position.x;
var targetX = currentX + 1.0f;
StartCoroutine(Move_Routine(currentX, targetX));
}
}
...
}
// I just added an optional duration value
// if you do not pass it it will be 1 second as you had it
// but this way you can still make it faster or slower without having
// to hardcode
// you also don't have to pass in the transform or if you do you should not call it transform
private IEnumerator Move_Routine(float from, float to, float duration = 1.0f)
{
if(alreadyLerping) yield break;
alreadyLerping = true;
var passedTime = 0f;
do
{
yield return new WaitForFixedUpdate();
var lerpfactor = passedTime / duration;
var currentX = Mathf.SmoothStep(from, to, lerpfactor);
playerRigidbody.MovePosition(new Vector3(currentX, transform.position.y, transform.position.z));
passedTime += Time.deltaTime;
} while (passedTime < duration);
// Just to be sure there is no under/overshooting I would
// always set the fixed value in the end
playerRigidbody.MovePosition(new Vector3(to, transform.position.y, transform.position.z));
// release the flag
alreadyLerping = false;
}
или, если хотите, вариант StopCoroutine
private IEnumerator currentRoutine;
private void FixedUpdate()
{
playerRigidbody.velocity = new Vector2(0.0f, 2.0f);
if (Input.GetKeyDown(KeyCode.RightArrow))
{
// only do if not lerping laready otherwise input is ignored
if (newBallPos != 2)
{
var currentX = transform.position.x;
var targetX = currentX + 1.0f;
if(currentRoutine!=null) StopCoroutine(currentRoutine);
currentRoutine = Move_Routine(currentX, targetX);
StartCoroutine(currentRoutine);
}
}
...
}