0

I am making a 2d top down game where the player can rotate the camera around himself as he moves through the world.

Everything works fine when the player is moving around the world the camera follows him fine. if he standing still then the camera rotation also works very well. However as soon as I start to do both then there is a jittery in the camera that makes all other objects jitter besides the player.

Now in working with this problem I have found out that this could have to do with the fact that I use rigidbody2d.AddRelativeForce (so physics) to move the player and that his movements are checked in FixedUpdate.

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

I have tried moving my camera rotation and the following scripts to LateUpdate, FixedUpdate, Update you name it. Nothing seems to work. I am sure that there is some sort of delay between movement of the camera and the rotation that is causing this. I am wondering if anyone has any feedback?

I have tried disabling Vsync, does not remove it entirely I have tried interpolating and extrapolating the rigidbody and although there is a difference it does not remove it entirely. Ironically it seemd if I have it set to none, it works best.

Scripts:

To Follow character, script applied to a gameobject that has the camera as a child

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

} The character Controller, script applied to the Player, is called in 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);
      }
  }
SteenPetersen
  • 188
  • 2
  • 17

2 Answers2

1

Try to use Coroutines. I modified some of my scripts to be more familiar to Your code, tried it, and I didn't see any jittery. I hope that will help You.

Camera Class:

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

Player Class:

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

}

Woltus
  • 438
  • 4
  • 14
  • Hi there, thanks for some input. I have tried to get your scripts to your run and cant get anything out of them. I am using 2D so unsure if that hanges anything. I have created a new player with the player script and a new camera with your camera script. – SteenPetersen May 10 '17 at 16:48
  • https://www.youtube.com/watch?v=sCqQYILenzw here is a video of the problem im facing. – SteenPetersen May 10 '17 at 16:51
0

I fixed this problem finally:

First I made my cameraRotation() and follow() into 1 function and gave it a better clearer name:

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

I then called that function from the character controller straight after the handling of movement. Both calls (handleMovement & cameraPosition) in fixedUpdate.

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

and the jittering was gone.

So it seems it was imply because there was a slight delay between the two calls as the previous posts I read had said. But I had failed to be able to properly Set them close enough together.

Hope this helps someone.

SteenPetersen
  • 188
  • 2
  • 17