Player jitters when camera rotates

I have a bit of a custom camera script in the works and there is one thing that isn’t working quite right. The way I have this set up is the camera will orbit around freely (using the MouseOrbit script) until a key is pressed and then it will face the direction the camera is facing. That works great. I locked down the rotation axes minus the Y axis. (Did that a few different ways but kept the simple way for now.) But when I rotate the camera for the character to rotate with it the character sort of jitters. I don’t exactly know what’s going on. Here’s the script dealing with camera. I’m going to keep messing with this.

function Update()
{
	var cam : Transform = Camera.main.transform;
	var camDir = cam.TransformDirection(Vector3.forward);
	var faceCam = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(camDir.normalized), 20 * Time.deltaTime);
	if (Input.GetAxis("Vertical") > 0)
	{
		transform.rotation = faceCam;
		transform.rotation.x = 0;
		transform.rotation.z = 0;
	}
			
	if (Input.GetAxis("Vertical") < 0)
	{
		transform.rotation = faceCam;
			
		transform.rotation.x = 0;
		transform.rotation.z = 0;
	}
			
	if (Input.GetAxis("Horizontal") > 0)
	{
		transform.rotation = faceCam;

		transform.rotation.x = 0;
		transform.rotation.z = 0;
	}
		
	if (Input.GetAxis("Horizontal") < 0)
	{
		transform.rotation = faceCam;
			
		transform.rotation.x = 0;
		transform.rotation.z = 0;
	}
}

Thank you!

I recently had a very similar jittery problem. Took me ages to figure out… I used the Penelope controls for the movement and then built a custom runtime input configuration system to handle the keys.

I noticed that my code for testing wether the key is pressed or released was being tested during each Update as opposed to being fired using my OnButtonDown and OnButtonUp events. Once I stopped checking for “should the player move or not” the jittering stopped.

Of course, then I also noticed that when moving towards the camera, the character attempts to do just that… moves towards the floating camera… as in, flies… anyways, separate problem. The thing is, I couldn’t figure out why the jittering occurred because all the code seemed fine. It turned out it was the constant start- and stop movement code that caused it. Not sure if this is relevant, but I thought I’d mention it…

Thank you for the reply.

What exactly do you mean by stop checking for should the player move or not? Also, I’m using the dot Move script and Character Controller to move the character.

I created a runtime buttin config so players could choose their own keyboard buttons as well as alternate keyboard buttons and a joystick i put for each of the various buttons used by the game. I then send a message to my components saying OnKeyDown and OnKeyUp for each button as appropriate. For the movement control I put the test for
if (myinput.isPressed[x]) and I placed it inside Update and I handled the actions as appropriate right there.

I then left the code to move/rotate in there bit I moved the tests for button up and button down to their respective callback functions and the jittering stopped. Now obviously our method of implmentation differ but in my case it was the fact that I started and stopped my movement code often. Perhaps in your case some of yoir code. Belongs in Update while others. Belong in FixedUpdate. I’m afraid I just don’t know. I am merely sharing my experience in the hopes that it migjt lead you to a EUREKA!!! moment :slight_smile:

Sorry for being so lost but I’m not fully following you. What I’m getting from your explanation is I’ll need to place my key pressing in a custom function and then call the movement code from those functions or from Update/FixedUpdate? But if I call back and forth wouldn’t that require a good number of booleans? (I have a few different movements from different keys.) Or I’m just plain oblivious. haha So sorry.

I can think of a few reasons why you would get problems with this code. For one you cant rely on if (x > 0) when x is a float… sometimes you will have strange errors where x = 0.00000000001 for seemingly no reason at all. This shouldn’t really happen with the Input axes because they already have a dead-zone coded into them.

Anyways, that’s not the real problem. The problem is that you are getting a Quaternion by Slerping between the current rotation and the destination rotation, applying this Quaternion, and then removing the x,z rotation. Instead you should do this:

var cam : Transform = Camera.main.transform;
var camDir = [B]cam.forward; //no need to use TransformDirection(Vector3.forward) for local forward...[/B]
camDir.y = 0; //remove vertical component of camDir
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(camDir), 20* Time.deltaTime);

I removed the “Input.GetAxis” stuff because it doesn’t seem necessary here and will certainly create jerky movement.
You could also change 20 * Time.deltaTime to something more reasonable like 4*Time.deltaTime which would help smooth it out as well.

Thank you for that great reply! But the thing is I don’t want the character always rotating with the camera. Only when I press a button then face forward and rotate with the camera. I split up the Input axes because I wanted the character to face the camera for whichever directional button the player presses. And I want the character to rotate faster. For some reason the character still jitters even when I take out that Input.GetAxis mess.

One thing… and it is pretty big… Change all of the transform.rotation’s to transform.localEulerAngles

transform.rotation.x = 0;
transform.rotation.z = 0;

// should be
transform.localEulerAngles.x = 0;
transform.localEulerAngles.z = 0;

I am not sure this will fix your problem but it is not a good idea to set parts of a Quaternion. :wink:

What happens if you change “20 * Time.deltaTime” to just “Time.deltaTime”?

It’s best to avoid Euler angles all together. Also in this case I am guessing there’s no parent to this transform and thus rotation==localRotation

Yeah Antitheory is correct. There is no parent. But when I take out 20 * and just put Time.deltaTime it moves far too slowly.

Ok but I asked because I was curious to know whether it is moving smoothly or not (which it would most certainly should when you are Slerping like that. My guess is that the problem lies in the code controlling the movement of the camera itself… Or perhaps there is some other script also trying to change the rotation of this object?

You could try using LateUpdate() instead of Update()… depending on how the camera script is setup this might fix the problem but it may not…

I see, I see. Well, the only rotation in the entire controls script is the code dealing with Slerp. And I posted that part. I tried LateUpdate. No luck. The camera script I’m using is the default MouseOrbit script. That works fine for now but eventually I’m going to need to customize it to use camera collision. (I dread that. haha) But the jittering continues.

OK, I am confused at what you want, when I run your script and press any movement key, it makes the object that I have rotate towards the camera. I assigned the MouseOrbit to the camera, rotated it around and it did the same thing.

The assumption that I have is that you want to rotate the camera, press forward and move in that direction… Mind you, that is facing AWAY from the camera. (because moving towards the camera doesn’t make much sense to me I guess)

So to this end, I rewrote the code that you were using to correctly place the direction away from the camera instead of towards. And simplified it some. (and yes, localEulerAngles is what I used because localRotation is still a Quaternion and you should not be playing with individual numbers on a Quaternion.)

var lookRotationSpeed=20.0;
private var lastLookRotation : Quaternion;

function Start(){
	var relativePos = -(Camera.main.transform.position - transform.position);
	lastLookRotation=Quaternion.LookRotation(relativePos);
}

function Update(){
	transform.rotation = Quaternion.Slerp(transform.rotation, lastLookRotation, lookRotationSpeed* Time.deltaTime);
	transform.localEulerAngles=Vector3.Scale(transform.localEulerAngles, Vector3.up);
	
	if(Input.GetAxis("Vertical")!=0.0 || Input.GetAxis("Horizontal")!=0.0){
		var relativePos = -(Camera.main.transform.position - transform.position);
		lastLookRotation=Quaternion.LookRotation(relativePos);
	}
}

My apologizes. I was unclear. But yeah that’s what I’m looking for. Rotate around then press forward and then rotate to face away from the camera. The player seeing the back of the character type thing. Sorry for the misunderstanding. But thank you I will try this script right now.

Wow. I was going the long route. Thanks so much! I’ll take note on this method. That did exactly the same thing yet written shorter. But it still is exactly the same. Jittery. BUT I thank you for the lesson on relative camera direction. I’m still stumped on the jitteriness. Going to keep trying though.

Hmmmm… do yourself a favor, create an empty level, make one block, attach a move script and this controller to it, and the mouse look to teh camera. Does it still jitter?

It does not on my screen.

Alrighty. Let’s see.

Well it’s noticeable when I rotate the camera slowly. Did you put a character controller on it?

I’m sorry that this is dragging on for so long and seemingly making no progress of the initial issue.

No, but its all at work, I wouldn’t be able to test it til tomorrow.