Как исправить перемещение с прерываниями?

Общие вопросы о Unity3D

Как исправить перемещение с прерываниями?

Сообщение EIvanov 23 ноя 2023, 12:21

Есть игрок и камера следующая за игроком.
Баг заключается в том, что когда игрок движется, а камера следит за игроком (перемещается за ним), то кажется что окружение перемещается неравномерно (прерывисто).
Возникают задержки перемещения, как будто игрок на долю секунды замедляется, картинка прерывается, "дрожит", нет постоянной скорости перемещения, есть какие то рывки.
То есть либо это игрок дергается, неравномерно перемещается, либо камера за ним, либо что то не успевает обновиться (Update/LateUpdate).

Видео
В билде https://youtu.be/-wLJ2U29n20
В редакторе https://youtu.be/bIZ6Y0nFSIs
Дрожание игрока (это норма?) https://youtu.be/-5pZva_Oc_s



К игроку и камере привязаны скрипты.

Код камеры. Ищет игрока и следит за ним.
Синтаксис:
Используется csharp
using UnityEngine;

public class CameraController : MonoBehaviour
{
    private GameObject player;
    private Transform playerTransform;

    // Скорость смещения камеры.
    private float lerpSpeedX = 5f;
    private float lerpSpeedY = 1f;

    void Awake()
    {
        transform.SetParent(null); // Если камера внутри какого либо объекта (например Player) перемещаем её вне его, для корректного расчета позиции перемещения.

        player = GameObject.Find("Player");
        playerTransform = player.GetComponent<Transform>();
    }


    void LateUpdate()
    {
        Vector3 targetCamPos = new Vector3(playerTransform.position.x, transform.position.y, transform.position.z);
        float newX = targetCamPos.x;
        //float newX = Mathf.Lerp(transform.position.x, targetCamPos.x, lerpSpeedX*Time.deltaTime);
        float newY = Mathf.Lerp(transform.position.y, targetCamPos.y, lerpSpeedY);
        transform.position = new Vector3(newX, newY, transform.position.z);
    }

}
 


Код передвижения игрока.
Синтаксис:
Используется csharp
void FixedUpdate()
{
float horizontalInput = Input.GetAxis("Horizontal");
Vector3 movement = new Vector2(horizontalInput * playerRunSpeed, rb.velocity.y);
rb.velocity = movement;
}
 


Для исключения бага скрипта камеры, я удалял эту камеру и использовал синемашин. То есть создавал дефолтную виртуальную камеру синемашин и перетаскивал туда объект для слежения - игрока.
Баг не исчез.
Ставил у rigidbody 2d игрока интерполяцию. Баг стал значительно меньше, но не исчез.


Заметил, что баг появляется на частоте монитора 144 герц, при 60 баг почти не заметен (трудно определить на глаз, может бага и нет).
Как это исправить?
EIvanov
UNIт
 
Сообщения: 103
Зарегистрирован: 05 июл 2021, 17:23

Re: Как исправить перемещение с прерываниями?

Сообщение Saltant 23 ноя 2023, 16:00

инпуты принято считывать в Update а двигать rb в FixedUpdate
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Адепт
 
Сообщения: 2236
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
  • Сайт

Re: Как исправить перемещение с прерываниями?

Сообщение 1max1 23 ноя 2023, 18:20

Проблема в том что физика обновляется реже, чем твой экран, так что интерполяция - это и есть решение. Попробуй еще лерпать не только Y, но и X, и брать rb.position, а не трансформ, возможно будет плавней. Либо, код движения камеры переместить в фикс апдейт, после передвижения игрока.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Как исправить перемещение с прерываниями?

Сообщение EIvanov 24 ноя 2023, 08:31

Saltant писал(а):инпуты принято считывать в Update а двигать rb в FixedUpdate

За считывание инпутов у меня отвечает InputSystem - встроенная система/скрипт юнити.
В апдейте оно там или нет - я не знаю. Но эта система используется всеми и пришла на замену старой системе ввода.

Синтаксис:
Используется csharp
   
private void MoveX_canceled(UnityEngine.InputSystem.InputAction.CallbackContext obj)
{
float value = obj.ReadValue<float>();
horizontalInput = value; // При нажатии кнопки влево или вправо записываем в поле 1 или -1.
}



// А тут устанавливаем вектор движения.
void FixedUpdate()
{

Vector3 movement = new Vector2(horizontalInput * playerRunSpeed, rb.velocity.y);
rb.velocity = movement;
}
Всё как вы написали.


1max1 писал(а):Проблема в том что физика обновляется реже, чем твой экран, так что интерполяция - это и есть решение.
Попробуй еще лерпать не только Y, но и X, и брать rb.position, а не трансформ, возможно будет плавней. Либо, код движения камеры переместить в фикс апдейт, после передвижения игрока.

Можно пример кода? Я плохо понимаю лерпы и интерполяцию, да и вообще что происходит (
Я понял, что камера как то неверно рассчитывает позицию - рассинхрон фиксед апдейта и апдейта (+просадка фпс).
EIvanov
UNIт
 
Сообщения: 103
Зарегистрирован: 05 июл 2021, 17:23

Re: Как исправить перемещение с прерываниями?

Сообщение 1max1 24 ноя 2023, 16:52

А что там понимать, у тебя у самого в коде уже это есть просто закомменченно)

Синтаксис:
Используется csharp
    void LateUpdate()
    {
        Vector3 targetCamPos = new Vector3(playerTransform.position.x, playerTransform.position.y, transform.position.z);

        float newX = Mathf.Lerp(transform.position.x, targetCamPos.x, lerpSpeedX * Time.deltaTime);
        float newY = Mathf.Lerp(transform.position.y, targetCamPos.y, lerpSpeedY * Time.deltaTime);

        transform.position = new Vector3(newX, newY, transform.position.z);
    }
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51


Вернуться в Общие вопросы

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 11