How to get rotation degrees to work with if statements in GDScript?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By enceladus

Hello! This is my first post on here so I apologize if this is the wrong place to ask this or I’ve omitted any important information.

I have a 3D third-person camera setup with a camera, a spring arm and a spatial I’ve designated camera_pivot. what I’m trying to do is create a camera system where when you look down, the camera pivot rotates along the X axis to make the camera move upward to get a bird’s eye view, but when you look up, the pivot remains stationary and only the camera rotates. Put more simply, the camera moves up when you look down, but it doesn’t move down when you look up.

To achieve this, I’ve tried using an if statement so that if the camera’s X rotation is at 0 degrees or below, only the camera rotates, but if it’s above 0, the camera pivot rotates.

var min_camera_rot : float = 0
var max_camera_rot : float = 90
var min_pivot_rot : float = -45
var max_pivot_rot : float = 0

#(Irrelevant code omitted)

func _input(event):
	if event is InputEventMouseMotion:
		rotation_degrees.y -= event.relative.x * mouse_sensitivity

		if camera.rotation_degrees.x <= 0:
			camera.rotation_degrees.x -= event.relative.y * mouse_sensitivity
			camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, min_camera_rot, max_camera_rot)
		else:
			camera_pivot.rotation_degrees.x -= event.relative.y * mouse_sensitivity
			camera_pivot.rotation_degrees.x = clamp(camera_pivot.rotation_degrees.x, min_pivot_rot, max_pivot_rot)

But this results in the camera pivot rotating, but clamping at 0 degrees and not handing rotation off to the camera like it’s supposed to.

I’ve also considered making the if statement check whether camera is at a higher global y position than camera_pivot, but I couldn’t get that to work either.

:bust_in_silhouette: Reply From: CardboardComputers

I don’t know if this will completely solve your problem, but I should point out something about the following bit:

var min_camera_rot : float = 0
var max_camera_rot : float = 90
var min_pivot_rot : float = -45
var max_pivot_rot : float = 0
# ...
func _input(event):
    if event is InputEventMouseMotion:
        rotation_degrees.y -= event.relative.x * mouse_sensitivity
        if camera.rotation_degrees.x <= 0:
            camera.rotation_degrees.x -= event.relative.y * mouse_sensitivity
            camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, min_camera_rot, max_camera_rot)
        else:
        # ...

The inner if block checks the camera’s local rotation. This means that camera.rotation_degrees.x will never be less than 0 (since it gets clamped to 0 whenever it’s negative), and if it ever goes above 0 then the code will just start jumping to the else block, at least until something sets it back to 0 or less. As a result, as soon as the camera.rotation_degrees.x turns positive, the camera will never turn again.

I’m not exactly sure if this works in your case, but I would suggest removing the if block and instead using something like:

const min_camera_rot : float = 0
const max_camera_rot : float = 90
const min_pivot_rot : float = -45
const max_pivot_rot : float = min_camera_rot

# this records the actual x rotation that the camera should be pointing along
var view_rot_x : float = 0.0
# ...
func _input(event):
    if event is InputEventMouseMotion:
        rotation_degrees.y -= event.relative.x * mouse_sensitivity
        view_rot_x -= event.relative.y * mouse_sensitivity
        # no need for conditional here, just set and clamp both
        camera_pivot.rotation_degrees.x = clamp(view_rot_x, min_pivot_rot, max_pivot_rot)
        camera.rotation_degrees.x = clamp(view_rot_x, min_camera_rot, max_camera_rot)

This is effectively equivalent to an if block: “if the view’s x rotation should be below 0, then lock the camera’s rotation and rotate the pivot; otherwise, rotate the camera but don’t touch the pivot.”

Note that I usedmax_pivot_rot = min_camera_rot since I assume that you wouldn’t want any intersection in their ranges, and I also set them to constants, but of course those details depend on your intent. If you do want some range with intersection, you should be careful to split the total rotation between the two, or else the view would turn twice as fast in that range.

Thank you so much for your help! I had to add a clamp to view_rot_x to fix a bug, but after that, everything is working perfectly!

enceladus | 2022-03-14 04:24