Rotational "snapping" issue and how to fix it

Following along on the course, my spaceship would have its pitch and roll “snap” if moving all the way one way and then quickly reversing direction (see gif).

I was able to fix this by clamping the maximum change in pitch and roll per frame.

[SerializeField] float maxRotationalDelta = 4f;

private void ProcessRotation() {
	float pitchDueToPosition = transform.localPosition.y * positionPitchFactor;
	float pitchDueToMovement = yThrow * controlPitchFactor;
	float targetPitch = pitchDueToPosition + pitchDueToMovement;

	float yawDueToPosition = transform.localPosition.x * positionYawFactor;
	float targetYaw = yawDueToPosition;

	float rollDueToMovement = xThrow * controlRollFactor;
	float targetRoll = rollDueToMovement;

	//clamps pitch delta maximums per frame to prevent snapping
	float pitchCurrent = transform.localEulerAngles.x;
	float pitchDelta = Mathf.DeltaAngle(targetPitch, pitchCurrent);
	float pitch = pitchCurrent - Mathf.Clamp(pitchDelta, -maxRotationalDelta, maxRotationalDelta);

	//clamps roll delta maximums per frame to prevent snapping
	float rollCurrent = transform.localEulerAngles.z;
	float rollDelta = Mathf.DeltaAngle(targetRoll, rollCurrent);
	float roll = rollCurrent - Mathf.Clamp(rollDelta, -maxRotationalDelta, maxRotationalDelta);

	transform.localRotation = Quaternion.Euler(pitch, targetYaw, roll);
}
2 Likes

Nice solution. I found out that there is a checkbox in the Input Manager called “Snap” that fixes this problem as well.

https://docs.unity3d.com/Manual/ConventionalGameInput.html

7 Likes

Oh nice, that solution seems better all around. thanks!

1 Like

wow, that helps a lot :star_struck:

I had a similar solution, I created a buffer essentially between the input and current movement of the ship.

    float SoftenInput(float axisThrow, float current) {
        if(Mathf.Abs(current - axisThrow) > 0.05f)
            current = reactionMultiplier * (Mathf.Abs(axisThrow) + .2f) * (axisThrow < current ? -1f : 1f) * Time.deltaTime + current;
        return current;
    }

Basically the ship just tries to “catch up” to the current axis input.

1 Like

Damn! I’ve been losing my mind on this for a few days.

I’ve been trying to Mathf.Lerp between the values to smooth it out nicely. (Dont follow me down this rabbit hole unless you can actually make it work and show me how :slight_smile:

roll = Mathf.Lerp(currentRoll, xThrow * controlRollFactor, .1f);

I hadnt had any good answers in the actual course Q&A and thought I’d come here and ask for help.

Now I have some things to try with a different approach!

FrankTheTank

1

Feb '18

Nice solution. I found out that there is a checkbox in the Input Manager called “Snap” that fixes this problem as well.

https://docs.unity3d.com/Manual/ConventionalGameInput.html

Thanks for the easy fix!

Privacy & Terms