im making third person game and i followed Brackeys "THIRD PERSON MOVEMENT in Unity" YouTube tutorial. But when i rewrote script with rigidbody, player start jitter slowly to the ground. I dont know how to fix it, so if you have any ideas please help. Thanks
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControler : MonoBehaviour
{
public Rigidbody rb;
public Transform cam;
public float speed = 6f;
public float turnSmoothTime = 0.1f;
float turnSmoothVelocity;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 inputVector = new Vector3(horizontal, 0f, vertical).normalized;
if (inputVector.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(inputVector.x, inputVector.z) * Mathf.Rad2Deg + cam.eulerAngles.y;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
rb.MovePosition(rb.position + moveDir * speed * Time.deltaTime);
}
}
}
i tried to fix it by diffrent ways but all of this ways doesnt gave me the need result.
The problem is that you are mixing update and physics via Rigidbody. For this approach, you need to control movement and rotation in FixedUpdate, and not in the usual Update. Otherwise, Unity will pull the object in non-synchronous loops, and this very tremor will occur.
What exactly to do:
Move the traffic code from Update to FixedUpdate. At the same time, use Time.fixedDeltaTime instead of Time. deltaTime and you can use rb. MovePosition(rb. position + moveDir speed Time.fixedDeltaTime);
It is also better to do rotations physically correctly (via rb. MoveRotation), or leave transform. rotation, but then again inside FixedUpdate — and make sure that Rigidbody has interpolation enabled (Interpolation) to smooth out movement during rendering.
Check that the Rigidbody doesn't have any extra physical forces (for example, there is no extra script that pulls it down). It often helps to freeze Rotation by X and Z (in Rigidbody Constraints) so that the character doesn't fall over.
If you want to move the character manually, but at the same time use collisions, sometimes it's easier to enable isKinematic = true, and already safely rotate transform. But then there will be no complete physical interaction.
In general, the simplest thing to do is to make sure that all the physical calculation is done inside FixedUpdate, and that rigidbody is configured correctly (Freeze Rotation, Interpolate, etc..). Then there will be no shaking.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public Rigidbody rb;
public Transform cam;
public float speed = 6f;
public float turnSmoothTime = 0.1f;
private float turnSmoothVelocity;
private Vector3 inputVector;
private float targetAngle;
private void Awake()
{
rb = GetComponent<Rigidbody>();
// To smooth out the movement of the rigidbody between frames
rb.interpolation = RigidbodyInterpolation.Interpolate;
// So that the character doesn't collapse
rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
}
private void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
inputVector = new Vector3(horizontal, 0f, vertical).normalized;
if (inputVector.magnitude >= 0.1f)
{
targetAngle = Mathf.Atan2(inputVector.x, inputVector.z) * Mathf.Rad2Deg + cam.eulerAngles.y;
}
}
private void FixedUpdate()
{
// Move and turn only if there is an input
if (inputVector.magnitude >= 0.1f)
{
float angle = Mathf.SmoothDampAngle(
transform.eulerAngles.y,
targetAngle,
ref turnSmoothVelocity,
turnSmoothTime
);
rb.MoveRotation(Quaternion.Euler(0f, angle, 0f));
Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
rb.MovePosition(rb.position + moveDir * speed * Time.fixedDeltaTime);
}
}
}