Как интерполировать камеру, которая получает новое положение при каждом обновлении в Unity? - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть физическое гребное устройство, которое постоянно отправляет оставшуюся дистанцию ​​своей гребной гонки в Unity (то есть 350 м осталось для завершения гонки). Когда я пытаюсь соответствующим образом обновить позицию своего игрока (только по оси Z), движение меняется. Как я могу интерполировать такие движения, чтобы они были более плавными?

Моя первая попытка выглядела так:

void Update()
{
   player.position = new Vector3(player.position.x, player.position.y, 
   pm5.Pm5_distance);
}

Это привело к прерывистому движению, возможно потому, что игрок просто телепортировался на следующую позицию.

Далее я попытался перейти на следующую позицию, но я не уверен, правильно ли я это сделал или это работает вообще, поскольку мой игрок получает новую позицию в каждом кадре:

private float startTime;
private float journeyLength;
public float speed = 5.0F;

void Start()
{
    startTime = Time.time;
}

void Update()
{
    if (player.position != new Vector3(player.position.x, 
    player.position.y, pm5.Pm5_distance))
    {
        journeyLength = Vector3.Distance(player.position, new 
        Vector3(player.position.x, player.position.y, pm5.Pm5_distance));

        float distCovered = (Time.time - startTime) * speed;

        float fracJourney = distCovered / journeyLength;

        transform.position = Vector3.Lerp(player.position, new 
        Vector3(player.position.x, player.position.y, pm5.Pm5_distance), 
        fracJourney);
    }

}

Несмотря на то, что это не приводит к ошибкам, похоже, это не решает и мою проблему. Может быть, вся концепция неверна? Я был бы рад, если бы кто-нибудь мог помочь мне здесь.

ИЗМЕНИТЬ 25.04.19: После попытки с кодом моего Дэвида я приземлился здесь:

    void Update()
    {

        if (useLerpMovementModel)
        {
            float newDistance = pm5.Pm5_distance;

            if (player.position.z != newDistance)
            {
                // Distance moved
                float distCovered = journeyLength - pm5.Pm5_distance;

                // Fraction of journey completed = current distance divided by total distance.
                float fracJourney = distCovered / journeyLength;

                // Set our position as a fraction of the distance between the markers.
                transform.position = Vector3.Lerp(player.position, new Vector3(player.position.x, player.position.y, newDistance), fracJourney);
            }
        }
        else
        {
            player.position = new Vector3(player.position.x, player.position.y, journeyLength - pm5.Pm5_distance);
        }

    }

Я не уверен, что это вообще что-то делает, хотя с точки зрения сглаживания движения по сравнению с player.position = new Vector3(player.position.x, player.position.y, journeyLength - pm5.Pm5_distance);

1 Ответ

1 голос
/ 24 апреля 2019

Следующая строка на самом деле неверный расчет:

journeyLength = Vector3.Distance(player.position, new 
        Vector3(player.position.x, player.position.y, pm5.Pm5_distance));

Вам нужно будет сохранить позицию в начале и в конце пути, чтобы вы могли интерполировать позицию игрока между ними.

Я постараюсь объяснить, что необходимо, взяв ваш код и добавив комментарии. Я также включил изменения, которые я рекомендовал, а также другие:

private float journeyLength;
private Vector3 startPosition;
private Vector3 endPosition;

void Start()
{
    // The total length of the journey, let's imagine it's 100
    // This assumes that when this Start() method is called that
    // pm5.Pm5_distance is equal to the journey length
    journeyLength = pm5.Pm5_distance;
    // Store the player's starting position
    // This will be used to interpolate between start/end
    startPosition = player.position;
    // Store the position that the player will be at when the journey is complete
    // This will be used to interpolate between start/end
    endPosition = startPosition + Vector3.forward * journeyLength;
}

void Update()
{
    // I am assuming that 'pm5.Pm5_distance' is the remaining distance
    if (pm5.Pm5_distance > 0f) 
    {
        // Take the remaining distance from the total journey length to get
        // the current distance travelled. Let's imagine the remaining distance is 50:
        // This will end up being 100 - 50 = 50 units travelled into the journey
        float distCovered = journeyLength - pm5.Pm5_distance;

        // We now get the fraction of the journey that that distance equates to, 
        // which in this case will be 0.5
        float fracJourney = distCovered / journeyLength;

        // Interpolate the players position from where it originally started
        // to the position at the end of the journey (the one we calculated in Start())
        transform.position = Vector3.Lerp(startPosition, endPosition, fracJourney);
    }

}

В качестве заключительного замечания важно понять, как работает функция Vector3.Lerp(): Он принимает два вектора и интерполирует их между значениями от 0 до 1.

Если значение равно 0, возвращается первый вектор.

Если значение равно 1, то возвращается второй вектор.

Если значение равно 0,5, возвращается вектор, лежащий между ними.

Итак, вы можете видеть, что в приведенном выше примере fracJourney равен 0,5, что означает, что для в этом кадре позиция игрока будет точно на половине пути гонки. Но в следующем кадре fracJourney будет пересчитан и скажем что-то вроде 0,55. В этом кадре новая позиция будет рассчитываться лишь немного вперед от того места, где она была в предыдущем кадре.

Это продолжается и продолжается до тех пор, пока, в конце концов, расстояние до конца гонки не станет 0.

...