Как плавно изменить положение объекта X при движении объекта по оси Y? - PullRequest
0 голосов
/ 09 апреля 2019

Объект движется по оси Y, мне нужно плавно перемещать положение оси X.

void FixedUpdate()
{
   playerRigidbody.velocity = new Vector2(0.0f, 2.0f);

    if (Input.GetKeyDown(KeyCode.RightArrow))
    {
        if (newBallPos != 2)
        {
            Vector3 pos1 = this.transform.position;
            Vector3 pos2 = this.transform.position;
            pos2.x += 1f;
            StartCoroutine(Move_Routine(this.transform, pos1, pos2));
        }
    }

   ----
}

----

private IEnumerator Move_Routine(Transform transform, Vector3 from, Vector3 to)
{
    float t = 0f;
    while (t < 1f)
    {
        t += Time.deltaTime;

        transform.position = Vector3.Lerp(from, to, Mathf.SmoothStep(0f, 1f, t));
        yield return null;
    }
}

С этим кодом.Ось X изменяется, но со старым положением оси Y, и это создает дрожание для времени, когда ось X перемещается.

При нажатии стрелки мне нужно плавно изменить положение объекта X, продолжая двигаться по оси Y. (Iнеобходимо изменить позицию X на 1)

Благодарим Вас за помощь!

Ответы [ 2 ]

0 голосов
/ 10 апреля 2019

Во-первых, насколько я понимаю, вы только хотите сгладить значение 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.

  1. Вы не должны вообще использовать transform.position = на твердых телах, а playerRigidbody.position = или playerRigidbody.MovePosition(targetPosition)

  2. Coroutine выполняется при каждом вызове Update, но вы должны менять твердые тела только в FixedUpdate => вы можете использовать WaitForFixedUpdate в своей сопрограмме

  3. Третья проблема заключается в том, чтоВы можете запустить несколько сопрограмм одновременно, если снова нажать кнопку до завершения движения.=> Вы можете решить это просто с помощью флага 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);
        }
    }

    ...
}
0 голосов
/ 10 апреля 2019

Попробуйте добавить ось x к Time.smoothDeltaTime; в этом методе, значения усредняются по нескольким кадрам для более плавного эффекта, это предпочтение, но иногда может иметь заметное значение.

 pos2.x += Time.smoothDeltaTime;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...