Hi there so recently i have encountered an issue where the character jitters when move the character, since this game is an endless runner, the character is moving forward or backward, just left, right, up and down.
So for the camera follow that i am currently using now is Cinemachine Virtual Camera. I have tried almost every solution that i could find on the web and unity forums, which includes ~
- Ensuring my cinemachine camera and player movement is in a one consistent update method, both of them are in fixed update
- Used Interpolate in my rigidbody
- Using rb.MovePosition instead of using transform.position
- I have also checked with 0 damping to see whether it is a update issue but with 0 damping the character will still jitter.
Here is an example video of the jittery -------
Here is the player movement script ------
using UnityEngine;
using System;
using System.Collections;
public enum SIDE { Left, Mid, Right }
public enum HitX { Left, Mid, Right, None }
public enum HitY { Up, Mid, Down, None }
public enum HitZ { Forward, Mid, Backward, None }
public class Player : MonoBehaviour
{
[Header("Instance")]
public static Player get;
[Header("Movement")]
public float moveSpeed = 10f;
public float XValue = 2.5f;
public float speedDodge = 10f;
private float NewXPos = 0;
private float x;
[Header("Jump Settings")]
public float jumpForce = 7f;
private Rigidbody rb;
public bool isGrounded;
public bool inJump;
[SerializeField] private float gravityMultiplier = 2.5f;
[SerializeField] private float jumpBufferTime = 0.2f;
[SerializeField] private float coyoteTime = 0.1f;
private float lastGroundedTime;
private float lastJumpTime;
[Header("Roll Settings")]
public bool InRoll;
private float rollDuration = 0.7f;
private float rollCounter;
private CapsuleCollider playerCol;
private float originalColliderHeight;
private float originalColliderCenter;
[Header("Animation")]
private Animator anim;
public bool dontPlay;
private void Awake()
{
get = this;
}
private void Start()
{
rb = GetComponent<Rigidbody>();
anim = GetComponentInChildren<Animator>();
playerCol = GetComponent<CapsuleCollider>();
if (playerCol != null)
{
originalColliderHeight = playerCol.height;
originalColliderCenter = playerCol.center.y;
}
x = 0;
NewXPos = 0;
dontPlay = false;
}
private void Update()
{
HandleMobileInput();
if (isGrounded)
{
lastGroundedTime = Time.time;
}
CheckRoll();
}
private void HandleMobileInput()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
swipeStart = touch.position;
}
else if (touch.phase == TouchPhase.Ended)
{
swipeEnd = touch.position;
HandleSwipe();
}
}
}
private Vector2 swipeStart, swipeEnd;
private void HandleSwipe()
{
float swipeX = swipeEnd.x - swipeStart.x;
float swipeY = swipeEnd.y - swipeStart.y;
if (Mathf.Abs(swipeX) > Mathf.Abs(swipeY)) // Horizontal swipe
{
if (Mathf.Abs(swipeX) > 50f)
{
if (swipeX > 0 && NewXPos < XValue)
{
NewXPos += XValue;
if (!dontPlay && anim != null) anim.Play("dR");
}
else if (swipeX < 0 && NewXPos > -XValue)
{
NewXPos -= XValue;
if (!dontPlay && anim != null) anim.Play("dL");
}
}
}
else // Vertical swipe
{
if (swipeY > 50f) // Swipe up - Jump
{
lastJumpTime = Time.time;
}
else if (swipeY < -50f && isGrounded) // Swipe down - Roll
{
Roll();
}
}
}
private bool CanJump()
{
return Time.time - lastGroundedTime <= coyoteTime;
}
private void Jump()
{
if (CanJump() && !inJump && !InRoll)
{
float calculatedJumpForce = Mathf.Sqrt(jumpForce * -2f * Physics.gravity.y);
Debug.Log("Jump Force Applied: " + calculatedJumpForce);
rb.AddForce(Vector3.up * calculatedJumpForce, ForceMode.Impulse);
inJump = true;
isGrounded = false; // Prevent multiple jumps
lastJumpTime = Time.time; // Store jump time
anim.SetBool("Run", false);
if (anim != null) anim.Play("Jump");
}
}
private void ApplyBetterGravity()
{
if (!isGrounded && rb.velocity.y < 0) // Apply only when falling
{
rb.velocity += Vector3.up * Physics.gravity.y * (gravityMultiplier - 1) * Time.deltaTime;
}
}
private void FixedUpdate()
{
Vector3 targetPosition = new Vector3(
Mathf.Lerp(rb.position.x, NewXPos, Time.fixedDeltaTime * speedDodge),
rb.position.y,
rb.position.z
);
rb.MovePosition(targetPosition);
if (Time.time - lastJumpTime <= jumpBufferTime && CanJump())
{
Jump();
}
ApplyBetterGravity();
CheckGroundStatus(); // More accurate ground detection
}
private void CheckGroundStatus()
{
float groundCheckDistance = 0.8f; // Reduce distance for better accuracy
Vector3 origin = transform.position + Vector3.up * 0.5f; // Start slightly above feet
LayerMask groundLayer = LayerMask.GetMask("Ground");
Debug.DrawRay(origin, Vector3.down * groundCheckDistance, Color.green, 2);
bool wasGrounded = isGrounded;
isGrounded = Physics.Raycast(origin, Vector3.down, out RaycastHit hit, groundCheckDistance, groundLayer);
if (isGrounded)
{
if (!wasGrounded) // Just landed
{
Debug.Log("Landed on: " + hit.collider.gameObject.name);
inJump = false; // Reset jump state
}
anim.SetBool("Run", true);
}
else
{
Debug.Log("No Ground Detected!");
}
}
private void Roll()
{
if (!InRoll && isGrounded)
{
InRoll = true;
rollCounter = rollDuration;
if (playerCol != null)
{
playerCol.height = originalColliderHeight / 2f;
playerCol.center = new Vector3(0, originalColliderCenter / 2f, 0);
}
if (anim != null) anim.Play("Roll");
}
}
private void CheckRoll()
{
if (rollCounter > 0)
{
rollCounter -= Time.deltaTime;
if (rollCounter <= 0)
{
if (playerCol != null)
{
playerCol.height = originalColliderHeight;
playerCol.center = new Vector3(0, originalColliderCenter, 0);
}
InRoll = false;
}
}
}
//public void hitByCar()
//{
// deathAudioSource.PlayOneShot(deathAudioSource.clip);
//}
//public void CollectCoin()
//{
// lastCoinTime = Time.time;
// currentPitch = Mathf.Clamp(currentPitch + pitchIncrement, 1.0f, maxPitch);
// coinAudioSource.pitch = currentPitch;
// coinAudioSource.PlayOneShot(coinAudioSource.clip);
// m_Coins += addAmount * tm.multiplier;
//}
//private void calculateTime()
//{
// if (Time.time - lastCoinTime > pitchResetDelay && currentPitch > 1.0f)
// {
// currentPitch = Mathf.Lerp(currentPitch, 1.0f, Time.deltaTime * 2.0f);
// coinAudioSource.pitch = currentPitch;
// }
//}
}
So i am all out of ideas to fix this issues, any help would be appreciated. Thank you very much!