Stop rotation from being set from -3.14 to 3.14

Godot Version

Godot 4.3

Question

I’m working on a simple way to rotate my camera in increments, without using a timer or the like. I’m pretty sure I’ve gotten it to the point where it would work perfectly, but the way Godot automatically sets angles outside the range -3.14 to 3.14 into that range is messing it up. Is there any way to disable this?

Here’s the code, if you’re curious:

if (Input.IsActionJustPressed("cam_rot_left")
/*||  Input.IsActionJustPressed("cam_rot_right")*/
||  !checkRotateWithinThreshold())
{
	clockRotating((float) delta);
}

private void clockRotating(float delta)
{
	if (checkRotateWithinThreshold())
	{
		if (Input.IsActionJustPressed("cam_rot_left")
		/*||  Input.IsActionJustPressed("cam_rot_right")*/)
		{
			isRotatingClockwise = Input.IsActionJustPressed("cam_rot_left");

			if (isRotatingClockwise)
			{
				isRotationDest = Rotation.Y + camRotIncrement;
				//GD.Print(isRotationDest);
			}
		}
	}

	RotateY(camRotSpeed * delta);

	if (Rotation.Y >= isRotationDest)
	{
		Rotation = new Vector3(Rotation.X, isRotationDest, Rotation.Z);
		//GD.Print(Rotation.Y);
	}
}

The function checkRotateWithinThreshold() just returns whether the Rotation.Y is at or very close to (accounting for division rounding) an increment of 45°.

The above code works up until I rotate the camera to 3.14 radians, at which point Godot switches the values to negatives and messes up the math.

You can do this but in C#, I am using gdscript

if rotation > PI:
 rotation -= PI
if rotation < -PI:
 rotation += PI

What are you trying to achieve again? Do you want to click a button and have the character rotate 45 degrees smoothly? Or do you want to clamp the rotation of the character within -45 to 45 degrees range?

This question might be of some help Smooth Camera Pivoting with Stopping Points

This user needed a smoothly rotating camera that moved in steps, which sounds like what you are after as well?

The first thing.

Ok, then indeed solution provided by @gentlemanhal in this post should satisfy your requirements.

You just need to convert it to C# unfortunately, or you can always use GDScript for this one script - Godot allows to mix C# and GDScript together within the same project.

1 Like

I may have explained myself poorly: I believe my code will work as intended if Rotation.Y is never below zero.

I tried the following block at the beginning of clockRotating()

if (Rotation.Y < 0)
{
	Rotation = new Vector3(Rotation.X, Rotation.Y + (float) Math.PI * 2, Rotation.Z);
}

and it works more than it did last night! Now once it reaches 180° it rotates for one frame every time I press the button.

I have to be going soon, so I don’t have time to check thoroughly, but from what I can tell the problem seems to be that checkRotateWithinThreshold() always returns false once Rotation.Y reaches pi (a.k.a. negative pi). I probably just have to compensate for the modulus numerator being negative somehow. Here’s the function, for reference:

private bool checkRotateWithinThreshold()
{
	return 
	(
		Rotation.Y % camRotIncrement <= 0.0000001
		|| Rotation.Y % camRotIncrement >= camRotIncrement - 0.0000001
	);
}

I tried quickly running the same block of code as above before the return statement, and changing the first terms of each comparison to absolute values, but that makes the camera spin indefinitely. I’ll have to take a closer look another time.

I think you’re overenginerring this problem with your approach. What’s wrong with either @gentlemanhal solution mentioned before or mine in this post?

4 Likes

Oh sorry, I only had a chance to look at one suggestion last night. This framework of doing it makes so much more sense! I’ll just have to configure it a bit to go at a constant speed.

1 Like

just use quats

I did a bit of looking around and found out that GDScript has a method rotate_toward(), which looks like exactly what I want to make it go at a constant speed.

Is there an implementation of this in C#, or will I need to create a separate script in GDScript just for this if I want to use it?

It’s Mathf.RotateToward() in C#.

1 Like

Might as well add this, since it tripped me up, so someone else might find it useful: remember that this is basically a fancy clamp function, so to use it the way I wanted, it looked like:

Rotation = new Vector3(Rotation.X, Mathf.RotateToward(Rotation.Y, isRotatingTarget, camRotSpeed * delta), Rotation.Z);

I just tried changing this script to be for a ChacterBody3D (so I can parent it to the Camera3D and easily use the MoveAndSlide collision), and the strangest thing happened.

Where my rotation worked fine before, now when it targets and reaches 3.1415927, it flips negative; that itself isn’t weird iiuc, but it gets stuck in some kind of rounding loop, where every frame the actual Rotation.Y alternates between -3.141593 and -3.1415925.

Is there something I’m missing that’s different about doing this to a CharacterBody3D? Or maybe it has to do with the Camera3D being the child of another Node3D?