1
\$\begingroup\$

I'm trying to make a first-person character with a rigid body. I need a rigid body because I want to add areas where the gravity comes from different directions so I also need to rotate the character accordingly. And as far as I know you cant rotate a character controller.

So I wrote a script for movement and camera rotation.

The problem I now face is that the camera vibrates. I recorded this video to show it.

Why do I get this and how do I fix this?

Movement code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovementRigidBody : MonoBehaviour
{
    public float speed = 10.0f;
    public Rigidbody rb;
    public LayerMask groundLayers;

    public float jumpForce = 7;
    public CapsuleCollider col;

    float transelation;
    float straffe;

    // Start is called before the first frame update
    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
        rb = this.GetComponent<Rigidbody>();
        col = GetComponent<CapsuleCollider>();
    }

    // Update is called once per frame
    void Update()
    {
        transelation = Input.GetAxis("Vertical") * speed;
        straffe = Input.GetAxis("Horizontal") * speed;
        bool jumping = Input.GetKeyDown(KeyCode.Space);


        transelation *= Time.smoothDeltaTime;
        straffe *= Time.smoothDeltaTime;



        /*if (IsGrounded())
        {
            rb.useGravity = false;
        }
        else
        {
            rb.useGravity = true;
        }*/


        if (IsGrounded() && Input.GetKeyDown(KeyCode.Space))
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }

        if (Input.GetKeyDown("escape"))
        {
            Cursor.lockState = CursorLockMode.None;
        }


    }

    void FixedUpdate()
    {
        transform.Translate(straffe, 0, transelation);
    }

    private bool IsGrounded()
    {
        return Physics.CheckCapsule(col.bounds.center, new Vector3(col.bounds.center.x, col.bounds.min.y, col.bounds.center.z), col.radius * .9f, groundLayers);
    }
}

Mouse look code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseLookRigidBody : MonoBehaviour
{
    public float mouseSensitivity = 100f;

    public Transform playerBody;

    Rigidbody rig;

    float xRotation = 0f;

    // Start is called before the first frame update
    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
        rig = this.transform.parent.gameObject.GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    public void Update()
    {
        float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -90f, 90f);


        transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
        playerBody.Rotate(Vector3.up * mouseX);

    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Never mix transform manipulation (eg. transform.Translate) with rigidbody physics \$\endgroup\$ – DMGregory Jan 21 at 19:01
1
\$\begingroup\$

Avoid placing the camera on the player GameObject at all, unless it's provisional or you really know what you are doing.

In most cases most issues are solved if you have an independent camera object (not parented with the player in any shape or form) and use the Update or LateUpdate method to put it into the right position at every frame.

Physical effects occur within FixedUpdate, which does not synchronize with the (Late)Update frames. That can cause flickering and other issues with the camera. The object it is parented to might not flicker (which you can't see because it's first person view), but everything else will.

Handling a camera is a bit mathematically challenging, but you can also use free assets or Unity's Standard Assets pack (a bit outdated, but still works fine).

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I tried this but I can't get my script to work. I was able to make the camera follow the player but now I can only look up and down. and the vibrating problem is still there \$\endgroup\$ – yente paternotte Jan 22 at 12:34
  • \$\begingroup\$ I also tried the standard one from unity ut it has the same issue. \$\endgroup\$ – yente paternotte Jan 22 at 12:35
  • \$\begingroup\$ @yentepaternotte - The standard one too? Sure you deactivated all other scripts from your side affecting the camera (if necessary removed them)? Because especially the standard camera is meant to work with most typical player movement scenarios. \$\endgroup\$ – Battle Jan 22 at 14:35
  • \$\begingroup\$ I even created a new project to test the standard ones. but I'm getting a feeling that there is something wrong with my mouse. because I have it in some games too but not as much. I tried with another mouse but that also does not change anything. \$\endgroup\$ – yente paternotte Jan 22 at 14:45
0
\$\begingroup\$

This is likely caused by the physics engine updating your character out of sync with the rendering framerate, which is normal.

The standard way to avoid this is to turn on interpolation for your player gameobject. Interpolation is perfect if you use a kinematic rigidbody as your player, and a good compromise if you use a dynamic rigidbody.

You can also make your physics framerate faster if you can afford it, 1/75th can help, or set it to a multiple of your ideal framerate, to mitigate the issue.

Other problems may be that you're using the transform to move your rigidbody instead of calls to MovePosition, AddForce or velocity.

If you have a dynamic rigidbody, and you don't like the camera lag caused by standard interpolation, you can use the current velocity and a raycast to guess the position of the rigidbody during the next render frame.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.