I'm new to Godot and have only about a year of experience of coding within Unreal Engine. I'm attempting to make a player controller similar to Deus Ex's as a starting off point to make a larger project down the line. So far, the only mechanics that I have are the basic movements (W forward, A left, D right, S backward, and mouse to look), crouching, jumping, and leaning - all of which were from many different youtube tutorials.
The issue at hand is adding a walk/sprint function in GDscript. My entire player script is this:
`extends CharacterBody3D
Export a variable to adjust sensitivity from the editor
@export var sensitivity: float = 0.002
@export var jog_speed = 5
@export var walk_speed = 3.5
@export var sprint_speed = 6
@export var crouch_speed = 3
@export var crouch_height = 0.90
@export var stand_height = 1.9
@export var jump_velocity = 4
var target_speed
var crouching = false
var is_moving = false
var is_walking = false
var is_sprinting = false
Leaning vars
var lean_angle : float = 15.0
var lean_offset : float = 0.35
var lean_speed : float = 8.0
var target_lean : float = 0.0 # -1 = Left, 1 = Right
var current_lean : float = 0.0
Define a reference to the vertical pivot node (e.g., a "Head" Node3D)
@onready var collision_shape = $CollisionShape3D
@onready var head = $Node3D
@onready var bonker = $HeadBonker
@onready var camera_3d = $Node3D/Camera3D
var camera_rotation_x: float = 0.0
Get gravity from project settings to keep consistent
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
Hide cursor
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _unhandled_input(event: InputEvent) -> void:
Check for mouse motion events
if event is InputEventMouseMotion:
Horizontal rotation (Y-axis) applied to the main body
rotation.y -= event.relative.x * sensitivity
# Vertical rotation (X-axis) applied to the head/camera pivot
camera_rotation_x -= event.relative.y * sensitivity
# Clamp the vertical rotation to prevent the camera from flipping upside down
camera_rotation_x = clampf(camera_rotation_x, deg_to_rad(-90), deg_to_rad(80))
head.rotation.x = camera_rotation_x
# Optional: You can also use the mouse's relative movement in _process or _physics_process
# by accumulating the event.relative value in a variable
func _input(event : InputEvent) -> void:
if Input.is_action_pressed("lean_left"):
if !crouching and is_moving:
target_lean = 0.0
else:
target_lean = -1.0
elif Input.is_action_pressed("lean_right"):
if !crouching and is_moving:
target_lean = 0.0
else:
target_lean = 1.0
else:
target_lean = 0.0
func _physics_process(delta):
target_speed = jog_speed
var head_bonked = false
if bonker.is_colliding():
head_bonked = true
# Jump
if not is_on_floor():
velocity.y -= gravity * delta
if Input.is_action_just_pressed("jump") and is_on_floor() and !crouching:
velocity.y = jump_velocity
if head_bonked:
velocity.y = -2
# Crouch/Stand mechanism
if Input.is_action_pressed("crouch"):
collision_shape.shape.height -= crouch_speed * delta
target_speed = crouch_speed
crouching = true
elif not head_bonked:
collision_shape.shape.height += crouch_speed * delta
crouching = false
if crouching:
target_speed = crouch_speed
collision_shape.shape.height = clamp(collision_shape.shape.height, crouch_height, stand_height)
if Input.is_action_just_pressed("walk") and !is_walking:
if !crouching:
target_speed = walk_speed
is_walking = true
print(target_speed)
elif is_walking:
target_speed = jog_speed
is_walking = false
print(target_speed)
# Get input direction
var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
# Calculate movement relative to the player's current rotation
var direction = (head.global_transform.basis * Vector3(input_dir.x, 0, input_dir.y))
direction.y = 0
if direction:
velocity.x = direction.x * target_speed
velocity.z = direction.z * target_speed
is_moving = true
else:
velocity.x = move_toward(velocity.x, 0, target_speed)
velocity.z = move_toward(velocity.z, 0, target_speed)
is_moving = false
# Head lean
current_lean = lerp(current_lean, target_lean, delta * lean_speed)
var target_tilt : float = deg_to_rad(-lean_angle) * current_lean
var target_offset : float = lean_offset * current_lean
camera_3d.rotation.z = lerp(camera_3d.rotation.z, target_tilt, delta * lean_speed)
camera_3d.position.x = lerp(camera_3d.position.x, target_offset, delta * lean_speed)
move_and_slide()`
When testing the "walk" function, I print the target_speed, which should change the speed of the player when the "walk" button is just pressed. The print shows that it is successfully changing the target_speed from the jog_speed (5) to the walk_speed (3.5), but there is no change of speed in the preview window.
Noting that the code for the stand/crouch function works completely as intended and reduces the player's speed to crouch_speed (3), what's different about the walk/jog code that makes it behave differently?
*** I'm "self-taught" from a bunch of stand alone tutorials and have had to figure out the best optimization methods for simply getting things to work. If there are mistakes I've made in the construction of this code that'll make it harder down the line or any important info I may have omitted please let me know 🙂