Дрожание камеры при вращении и перемещении - 2D сверху вниз Unity

Я делаю 2d сверху вниз игру, где игрок может вращать камеру вокруг себя, когда он движется по миру.

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

Теперь, работая с этой проблемой, я обнаружил, что это может быть связано с тем, что я использую hardbody2d.AddRelativeForce (то есть физику) для перемещения игрока и что его движения проверяются в FixedUpdate.

https://forum.unity3d.com/threads/camera-jitter-problem.115224/ http://answers.unity3d.com/questions/381317/camera-rotation-jitterness-lookat.html

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

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

Сценарии:

Чтобы следовать за персонажем, скрипт применяется к игровому объекту, у которого есть камера в детстве

  public class FollowPlayer : MonoBehaviour {

  public Transform lookAt;
  public Spawner spawner;
  private Transform trans;
  public float cameraRot = 3;

  private bool smooth = false;
  private float smoothSpeed = 30f;
  private Vector3 offset = new Vector3(0, 0, -6.5f);

  //test
  public bool changeUpdate;

  private void Start()
  {
      trans = GetComponent<Transform>();
  }

  private void FixedUpdate()
  {
      CameraRotation();
  }

  private void LateUpdate()
  {
      following();
  }

  public void following()
  {

      Vector3 desiredPosition = lookAt.transform.position + offset;

      if (smooth)
      {
          transform.position = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
      }
      else
      {
          transform.position = desiredPosition;
      }
  }

  void CameraRotation()
  {
      if (Input.GetKey("q"))
      {
          transform.Rotate(0, 0, cameraRot);
      }

      if (Input.GetKey("e"))
      {
          transform.Rotate(0, 0, -cameraRot);
      }
  }

  public void SetTarget(string e)
  {
      lookAt = GameObject.Find(e).GetComponent<Transform>();
  }

}Контроллер персонажа, скрипт, примененный к Игроку, вызывается в FixedUpdate

      private void HandleMovement()
  {

      if (Input.GetKey("w"))
      {
          rigid.AddRelativeForce(Vector2.up * speed);
      }

      if (Input.GetKey("s"))
      {
          rigid.AddRelativeForce(Vector2.down * speed);
      }

      if (Input.GetKey("a"))
      {
          if (facingRight)
          {
              Flip();
          }
          rigid.AddRelativeForce(Vector2.left * speed);
      }

      if (Input.GetKey("d"))
      {
          if (!facingRight)
          {
              Flip();
          }
          rigid.AddRelativeForce(new Vector2(1,0) * speed);
      }
  }

2 ответа

Решение

Я наконец исправил эту проблему:

Сначала я превратил cameraRotation() и follow() в 1 функцию и дал ей более понятное имя:

    public void UpdateCameraPosition()
{
    if (Input.GetKey("q"))
    {
        transform.Rotate(0, 0, cameraRot);
    }
    else if (Input.GetKey("e"))
    {
        transform.Rotate(0, 0, -cameraRot);
    }

    Vector3 desiredPosition = lookAt.transform.position + offset;

    transform.position = desiredPosition;
}

Затем я вызвал эту функцию из контроллера персонажа сразу после обработки движения. Оба вызова (handleMovement и cameraPosition) в fixedUpdate.

 void FixedUpdate()
{
    HandleMovement();                         
    cameraController.UpdateCameraPosition(); 
}

и дрожание исчезло.

Так что, похоже, это подразумевалось, потому что между двумя звонками была небольшая задержка, как и в предыдущих постах, которые я прочитал. Но я не смог правильно установить их достаточно близко друг к другу.

Надеюсь, это кому-нибудь поможет.

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

Класс камеры:

public class CameraController : MonoBehaviour {

    [SerializeField]
    Transform CameraRotator, Player;

    [SerializeField]
    float rotationSpeed = 10f;

    float rotation;

    bool rotating = true;

    void Start()
    {
        StartCoroutine(RotatingCamera());
    }

    IEnumerator RotatingCamera()
    {
        while (rotating)
        {
            rotation = Input.GetAxis("HorizontalRotation");
            CameraRotator.Rotate(Vector3.up * Time.deltaTime * rotation * rotationSpeed);
            CameraRotator.position = Player.position;
            yield return new WaitForFixedUpdate();
        }
    }

    private void OnDestroy()
    {
        StopAllCoroutines();
    }
}

Класс игрока:

public class PlayerMovement : MonoBehaviour {

[SerializeField]
float movementSpeed = 500f;

Vector3 movementVector;
Vector3 forward;
Vector3 right;

[SerializeField]
Transform CameraRotator;

Rigidbody playerRigidbody;

float inputHorizontal, inputVertical;

void Awake()
{
    playerRigidbody = GetComponent<Rigidbody>();

    StartCoroutine(Moving());
}

IEnumerator Moving()
{
    while (true)
    {
        inputHorizontal = Input.GetAxis("Horizontal");
        inputVertical = Input.GetAxis("Vertical");

        forward = CameraRotator.TransformDirection(Vector3.forward);
        forward.y = 0;
        forward = forward.normalized;

        Vector3 right = new Vector3(forward.z, 0, -forward.x);

        movementVector = inputHorizontal * right + inputVertical * forward;

        movementVector = movementVector.normalized * movementSpeed * Time.deltaTime;

        playerRigidbody.AddForce(movementVector);
        yield return new WaitForFixedUpdate();
    }
}

}

Другие вопросы по тегам