v4.5.stable
So I’m an issue with my character model rotating towards the Z axis after jumping every time.
I currently have setup a FPP and a TPP and this is only occurring in the TPP. I have linked a video of what is occurring. If I disable the lines of code that allow the character to rotate in the direction of movement this issue goes away but then obviously it will no longer rotate. Any and all help is appreciated. Also sorry if the code isn’t posted correctly, I’m new to the forums..
Video: https://youtu.be/0a9B9jAYFA8
extends CharacterBody3D
#nodes
@export_group("Nodes")
#Character root node.
@export var character : CharacterBody3D
#Head node.
@export var head : Node3D
#Settings.
@export_group("Settings")
#Mouse settings.
@export_subgroup("Mouse settings")
#mouse sensitivity.
@export_range(1, 100, 1) var mouse_sensitivity: int = 50
#pitch clamp settings.
@export_subgroup("Clamp settings")
#max pitch in degrees.
@export var max_pitch : float = 60
#min pitch in degrees.
@export var min_pitch : float = -89
@onready var pivot = $CamOrigin
@onready var pivot2 = $CamOrigin/Node3D
@onready var body = $CollisionShape3D
@onready var FPP = $CollisionShape3D/MeshInstance3D/Head/FPP
@onready var TPP = $CamOrigin/Node3D/SpringArm3D/TPP
@export var TPPSense = .01
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var speed = 5
var jump_height = 5
var jump_speed = 1.5
func _ready():
Input.set_use_accumulated_input(false)
pivot.set_as_top_level(true)
#Game pause + close
func _unhandled_input(event)->void:
if Input.mouse_mode != Input.MOUSE_MODE_CAPTURED:
if event is InputEventKey:
if event.is_action_pressed("ui_cancel"):
get_tree().quit()
if event is InputEventMouseButton:
if event.button_index == 1:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
return
if event is InputEventKey:
if event.is_action_pressed("ui_cancel"):
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
return
if FPP.is_current() and event is InputEventMouseMotion:
aim_look(event)
#Handles aim look with the mouse.
func aim_look(event: InputEventMouseMotion)-> void:
var viewport_transform: Transform2D = get_tree().root.get_final_transform()
var motion: Vector2 = event.xformed_by(viewport_transform).relative
var degrees_per_unit: float = 0.001
motion *= mouse_sensitivity
motion *= degrees_per_unit
add_yaw(motion.x)
add_pitch(motion.y)
clamp_pitch()
#Rotates the character around the local Y axis by a given amount (In degrees) to achieve yaw.
func add_yaw(amount)->void:
if is_zero_approx(amount):
return
character.rotate_object_local(Vector3.DOWN, deg_to_rad(amount))
character.orthonormalize()
#Rotates the head around the local x axis by a given amount (In degrees) to achieve pitch.
func add_pitch(amount)->void:
if is_zero_approx(amount):
return
head.rotate_object_local(Vector3.LEFT, deg_to_rad(amount))
head.orthonormalize()
#Clamps the pitch between min_pitch and max_pitch.
func clamp_pitch()->void:
if head.rotation.x > deg_to_rad(min_pitch) and head.rotation.x < deg_to_rad(max_pitch):
return
head.rotation.x = clamp(head.rotation.x, deg_to_rad(min_pitch), deg_to_rad(max_pitch))
head.orthonormalize()
#Jump + Movement + Gravity
func _physics_process(delta):
camera_follows_player()
velocity.y += -gravity * delta
move_and_slide()
if is_on_floor() and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED and Input.is_action_just_pressed("jump"):
velocity.y = jump_height
if FPP.is_current() and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED and velocity.y != 0:
var input = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
var movement_dir = transform.basis * Vector3(input.x, 0, input.y)
velocity.x = movement_dir.x * speed * jump_speed
velocity.z = movement_dir.z * speed * jump_speed
elif FPP.is_current() and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED and velocity.y == 0:
var input = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
var movement_dir = transform.basis * Vector3(input.x, 0, input.y)
velocity.x = movement_dir.x * speed
velocity.z = movement_dir.z * speed
if TPP.is_current() and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED and velocity.y != 0:
var input = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
var movement_dir = pivot.global_basis * Vector3(input.x, 0, input.y)
velocity.x = movement_dir.x * speed * jump_speed
velocity.z = movement_dir.z * speed * jump_speed
elif TPP.is_current() and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED and velocity.y == 0:
var input = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
var movement_dir = pivot.global_basis * Vector3(input.x, 0, input.y)
velocity.x = movement_dir.x * speed
velocity.z = movement_dir.z * speed
if TPP.is_current() and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED and velocity.length() > 0:
character.rotation.y = atan2(-velocity.x,-velocity.z)
character.orthonormalize()
func camera_follows_player():
var player_pos = global_transform.origin
pivot.global_transform.origin = Vector3(player_pos.x, player_pos.y + 2, player_pos.z)
pivot.orthonormalize()
#TPP camera controls + camera swap
func _input(event):
if TPP.is_current() and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED and event is InputEventMouseMotion:
pivot.rotate_object_local(Vector3.DOWN, event.relative.x * TPPSense)
pivot.orthonormalize()
pivot2.rotate_object_local(Vector3.LEFT, -event.relative.y * TPPSense)
pivot2.rotation.x = clamp(pivot2.rotation.x, deg_to_rad(-75.0), deg_to_rad(25))
pivot2.orthonormalize()
if Input.is_action_pressed("switch_perspective"):
if FPP.is_current():
FPP.clear_current(true)
elif TPP.is_current():
TPP.clear_current(true)