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

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

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

Теперь, работая с этой проблемой, я обнаружил, что это может быть связано с тем фактом, что я использую жесткое тело2d.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, но не удалил его полностью. Я пробовал интерполировать и экстраполировать твердое тело, и хотя есть разница, он не удаляет его полностью. По иронии судьбы мне показалось, что если у меня нет, это работает лучше всего.

Скрипты:

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

  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);
      }
  }

person SteenPetersen    schedule 09.05.2017    source источник


Ответы (2)


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

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

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();
    }
}

}

person Woltus    schedule 09.05.2017
comment
Привет, спасибо за ваш вклад. Я пытался запустить ваши сценарии и ничего не могу из них извлечь. Я использую 2D, поэтому не уверен, что это что-то меняет. Я создал новый плеер со скриптом плеера и новую камеру с вашим скриптом камеры. - person SteenPetersen; 10.05.2017
comment
youtube.com/watch?v=sCqQYILenzw вот видео о проблеме, с которой я столкнулся . - person SteenPetersen; 10.05.2017

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

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

    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(); 
}

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

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

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

person SteenPetersen    schedule 10.05.2017