CharacterController movement Jittery

I’ve got a CharacterController attached to my main character and I use it to move the character in my FixedUpdate method.

I have it working great and the character can walk/run in any angle/direction just fine. However when I walk at certain angles the character is very very jittery. It only seems to effect certain angles and is very sensitive to the movement speed. IE if my character runs everywhere then there is no jitter, but if I slow down and walk slowly there is tons and tons of jitter.

I’m at a loss on how to fix this, anyone ever seen this?

Can you post the code you are using with the CharacterController?

Yea here is the code in my FixedUpdate method:

void FixedUpdate () {
		PlayerState newState = PlayerState.Idle;
		// if player action is paused then ignore touchpad velocity
		if ((true == GameState.IsActionPaused()) || being.IsStunned()) {
			movementVelocity = Vector3.zero;
		} else {
			movementVelocity = touchPad.getMovement();
		}
		float xdist = Mathf.Abs(movementVelocity.x);
		float zdist = Mathf.Abs(movementVelocity.z);
		
		
		if (xdist > 0.2f || zdist > 0.2f) {
			newState = PlayerState.Running;
		} else if (xdist > minimumMoveSpeed || zdist > minimumMoveSpeed) {
			newState = PlayerState.Walking;
		}
		
		
		if (!character.isGrounded ||  (newState != PlayerState.Idle) ) {

			
			if ((newState != PlayerState.Idle)  (performingAttack == false)) {
			
				movementVelocity = movementVelocity.normalized;
				movementVelocity=cameraTransform.TransformDirection(movementVelocity);
				if (newState == PlayerState.Running) {
					movementVelocity *= runSpeed;
				} else {
					movementVelocity *= walkSpeed;
				}
				movementVelocity.y = 0;
			} else {
				movementVelocity = Vector3.zero;
			}
			
			// add gravity in so our magnitudes match up
			if (false == character.isGrounded) {
				movementVelocity.y += Physics.gravity.y;
			} 		
			
			if (jumpingState == PlayerState.Jumping) {
				movementVelocity.y +=Mathf.Lerp(jumpSpeed,0,jumping);
				jumping += Time.fixedDeltaTime;
				if (jumping >= 1) {
					jumpingState = PlayerState.Idle;
				}
			}
			character.Move(movementVelocity*Time.fixedDeltaTime);
			movementVelocity.y = 0;
			
			if (performingAttack == false) {

				
				
				if ((movementState == PlayerState.Idle)  (newState == PlayerState.Walking))
					PlayerAnimations.CrossFade(WalkAnimation.name);
				else if ((movementState == PlayerState.Idle) || (movementState == PlayerState.Walking)  (newState == PlayerState.Running))
					PlayerAnimations.CrossFade(RunAnimation.name);
				
				movementState = newState;
				lastMovementVector = movementVelocity;
			}
			
		} else {
			if (jumpingState == PlayerState.Jumping) {
				movementVelocity.y += Mathf.Lerp(jumpSpeed,0,jumping);
				jumping += Time.deltaTime;
				if (jumping >= 1) {
					jumpingState = PlayerState.Idle;
				}
				character.Move(movementVelocity*Time.fixedDeltaTime);
			} else {
				movementState = PlayerState.Idle;
				PlayerAnimations.CrossFade(IdleAnimation.name);
			}
		}
		UpdateDamageText();
	}

My touchPad object returns a vector between -1 and 1 for the velocity to move. I’ve had print statements in there while it was jittering to ensure it wasn’t the vector bouncing and it wasn’t, the vector returned was consistently the same value.

I had a similar problem and tried everything. The solution for me ended up being restarting Unity for some reason.
xian

Well this happens both in unity and on the iphone. I thought it was just delay between unity remote and unity but since it happens on the iphone also it’s a big problem as it makes my game look like amateurish when you walk at certain angles.

Why don’t you try playing around with this value in the character controller (I put the value in bold below). If you make it larger the character won’t turn unless more of an angle is reached on the thumbstick. The character will look increasingly like they are strafing, but hey, maybe that could be better than what you think is “amateurish” and jittery. :wink: -xian

Tried it and it didn’t help. BTW When I say jittery and amateurish I mean the character looks like he’s moving on land during a 9.5 magnitude earth quake. The jitter is REALLY bad.

I tried magnitudes from 0.001f to 0.1f and neither had any effect.

Which vector did you check, the input from the touchpad or the movementVelocity vector just before it is passed into the Move function? I think the jitter is caused by rapid alternation between the walking and running speeds. Try using the magnitude of the movementVelocity vector to select between walking and running speed rather than the maximum of X and Z speeds:-

movementVelocity.y = 0f;
float fwdSpeed = movementVelocity.magnitude;

if (fwdSpeed > 0.2f) {
    newState = PlayerState.Running; 
} else if (fwdSpeed > minimumMoveSpeed) { 
     newState = PlayerState.Walking; 
}

Tried that and it didn’t help. I also tried making it so that no matter what speed he moved at that he was walking and it still did it. It only does it at certain angles, never at other angles.

I also tried a combination of everything suggested and still no luck.

It might sound strange, but can you you roughly determine the angles where this happens? If it’s a mathematical problem, this information might help solve it.

Yea when I get home tonight I’ll put some print outs of the vector’s that are causing it.

Sorry it took so long but here’s a printout of the vector during jerky movement:
Movement vector =(-2.6, 0.0, -3.0)
Movement vector *Time.fixedDeltaTime=(-0.1, 0.0, -0.1)
Movement vector =(-2.6, 0.0, -3.0)
Movement vector *Time.fixedDeltaTime=(-0.1, 0.0, -0.1)
Movement vector =(-2.6, 0.0, -3.0)
Movement vector *Time.fixedDeltaTime=(-0.1, 0.0, -0.1)
Movement vector =(-2.6, 0.0, -3.0)
Movement vector *Time.fixedDeltaTime=(-0.1, 0.0, -0.1)
Movement vector =(-2.6, 0.0, -3.0)
Movement vector *Time.fixedDeltaTime=(-0.1, 0.0, -0.1)
Movement vector =(-2.6, 0.0, -3.0)
Movement vector *Time.fixedDeltaTime=(-0.1, 0.0, -0.1)

With this code:

void FixedUpdate () {
		PlayerState newState = PlayerState.Idle;
		// if player action is paused then ignore touchpad velocity
		if ((true == GameState.IsActionPaused()) || being.IsStunned()) {
			movementVelocity = Vector3.zero;
		} else {
			movementVelocity = touchPad.getMovement();
		}
		float xdist = Mathf.Abs(movementVelocity.x);
		float zdist = Mathf.Abs(movementVelocity.z);
		
		
		if (xdist > 0.2f || zdist > 0.2f) {
			newState = PlayerState.Running;
		} else if (xdist > minimumMoveSpeed || zdist > minimumMoveSpeed) {
			newState = PlayerState.Walking;
		}
		
		
		if (!character.isGrounded ||  (newState != PlayerState.Idle) ) {

			
			if ((newState != PlayerState.Idle)  (performingAttack == false)) {
			
				movementVelocity = movementVelocity.normalized;
				movementVelocity=cameraTransform.TransformDirection(movementVelocity);
				if (newState == PlayerState.Running) {
					movementVelocity *= runSpeed;
				} else {
					movementVelocity *= walkSpeed;
				}
				movementVelocity.y = 0;
			} else {
				movementVelocity = Vector3.zero;
			}
			Debug.Log("Movement vector ="+movementVelocity);
			Debug.Log("Movement vector *Time.fixedDeltaTime="+movementVelocity*Time.fixedDeltaTime);
			// add gravity in so our magnitudes match up
			if (false == character.isGrounded) {
				movementVelocity.y += Physics.gravity.y;
			} 		
			
			if (jumpingState == PlayerState.Jumping) {
				movementVelocity.y +=Mathf.Lerp(jumpSpeed,0,jumping);
				jumping += Time.fixedDeltaTime;
				if (jumping >= 1) {
					jumpingState = PlayerState.Idle;
				}
			}
			character.Move(movementVelocity*Time.fixedDeltaTime);
			movementVelocity.y = 0;
			
			if (performingAttack == false) {

				
				
				if ((movementState == PlayerState.Idle)  (newState == PlayerState.Walking))
					PlayerAnimations.CrossFade(WalkAnimation.name);
				else if ((movementState == PlayerState.Idle) || (movementState == PlayerState.Walking)  (newState == PlayerState.Running))
					PlayerAnimations.CrossFade(RunAnimation.name);
				
				movementState = newState;
				lastMovementVector = movementVelocity;
			}
			
		} else {
			if (jumpingState == PlayerState.Jumping) {
				movementVelocity.y += Mathf.Lerp(jumpSpeed,0,jumping);
				jumping += Time.deltaTime;
				if (jumping >= 1) {
					jumpingState = PlayerState.Idle;
				}
				character.Move(movementVelocity*Time.fixedDeltaTime);
			} else {
				movementState = PlayerState.Idle;
				PlayerAnimations.CrossFade(IdleAnimation.name);
			}
		}
		UpdateDamageText();
	}

If the movement vector is exactly the same each time, but the actual movement is still jittery, it suggests there is some problem with the physics. Is it possible that the character starts off with its collider partly stuck in the ground or something like that?

Doubtful. It only happens when I move certain directions and I can jump and land over and over and it still happens at the same angles.

Hi bpatters, were you able to get around your jittery problem? 'coz I think I’m having the same problems (my objects, when dragged at a specific angle, go up and down as if they’re jumping).

Welcome to the forum, Dendrobium!

Can you post the code that is giving you this problem?

Do the jitters disappear if you do the movement in Update rather than FixedUpdate?

I was experiencing the same issue myself. My character was a simple capsule with a scaled cube as a ‘face’. I was having jitter issues but it was really only on angles. What I noticed, after using the awesome profiler, was that it was the .Move method of the character controller that was really slow. So I thought about it for a minute and then I realized that the cube itself still has a Box collision component on it. The capsule had its own collision component as well and these two things were penetrating each other. Disabling it on the “face” fixed my issues and my character controller is smooth again.

Have you verified that you only have 1 collision component for all the parts that make up your character?

Wow, this is crazy… I was trying to debug this exact issue for ages, funny thing is it only became massively visible just recently when I switched from mesh’s to terrains on iOS.

I’d tried swapping out the camera a bunch of different code then after reading this went… hmm no way it could be the box i’m using for raycast restrictions with touch based movement. Needless to say as soon as I moved the box off the terrain i was back up to significantly smoother movement. Thanks for the tip

Had this problem, decided not to use Character controller, jittery and appears to be skipping animation frames.