How to make my character run?

Godot Version

Godot_v4.3-stable_win64

Question

How can I make my character run while holding shift while moving?

Hi, I was following a tutorial for a third person character controller and was wondering where and how to get my character to run. I have an input event connected to the shift key and after trying to add an approach where the walk_speed and run_speed are different, I just can’t figure out where to add that to this script or if I need to use a different approach. To add onto that would I need a separate running sound or could I reuse that for my running code and just make the effect faster? When I added a running animation the model just stops moving as well.

extends CharacterBody3D

@export_group("Camera")
@export_range(0.0, 1.0) var mouse_sensitivity := 0.25

@export_group("Movement")
@export var move_speed := 8.0
@export var acceleration := 20.0


var _camera_input_direction := Vector2.ZERO
var _last_movement_direction := Vector3.BACK

@onready var _camera_pivot: Node3D = %CameraPivot
@onready var _camera: Camera3D = %Camera3D
@onready var _Skin: Node3D = %CooperSkin
@onready var _WalkSound: AudioStreamPlayer3D = %WalkSound

func _input(event: InputEvent) -> void:
	if event.is_action_pressed("left_click"):
		Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	if event.is_action_pressed("Alt"):
		Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
	if event.is_action_pressed("PhotoMode"):
		_Skin.visible = false

func _unhandled_input(event: InputEvent) -> void:
	var is_camera_motion :=(
		event is InputEventMouseMotion and 
		Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED
	)
	if is_camera_motion:
		_camera_input_direction = event.screen_relative * mouse_sensitivity

func _ready():
	pass


func _physics_process(delta: float) -> void:
	#Scene Navigation -----------------------------
	#Input = "R"
	if Input.is_action_just_pressed("Restart"):
		get_tree().reload_current_scene()
	
	#Input = "Esc"
	if Input.is_action_just_pressed("Exit"):
		get_tree().quit()
	
	#Input = "3"
	if Input.is_action_just_pressed("DeathTest"):
		#Insert Death Animations & Processes here!
		pass
#--------------------------------------------------
#Camera Controls 
	_camera_pivot.rotation.x += _camera_input_direction.y * delta
	_camera_pivot.rotation.x = clamp(_camera_pivot.rotation.x, -PI / 6.0, PI / 3.0)
	_camera_pivot.rotation.y -= _camera_input_direction.x * delta
	
	_camera_input_direction = Vector2.ZERO
	
	#------------------------------------------------
	#Movement Controls
	var raw_input := Input.get_vector("Forward","Backward", "Left", "Right")
	var forward := _camera.global_basis.x
	var right := _camera.global_basis.z
	
	var move_direction := forward * raw_input.y + right * raw_input.x
	move_direction.y = 0.0
	move_direction = move_direction.normalized()
	
	velocity = velocity.move_toward(move_direction * move_speed, acceleration * delta)
	move_and_slide()
	
	if move_direction.length() > 0.2:
		_last_movement_direction = move_direction
	var target_angle := Vector3.BACK.signed_angle_to(_last_movement_direction, Vector3.UP)
	_Skin.global_rotation.y = target_angle
	
	var ground_speed := velocity.length()
	var AP = $CooperSkin/AnimationPlayer
	if ground_speed > 0.0:
		AP.play("Walk002")
		if $Timer.time_left <= 0:
			%WalkSound.play()
			$Timer.start(0.9)
	else:
		AP.play("Idle02")
		
	if Input.is_action_pressed("Run"):
		AP.play("Run001")

One thing at a time I think is best here. The first thing you can do is to change your move_speed when the shift button is pressed, and change it back when the shift button is released.

Something like (with “sprint” assigned to whatever button you want)

	if event.is_action_pressed("sprint"):
		move_speed = 16
	elif event.is_action_released("sprint"):
		move_speed = 8

Hope that helps in some way.

I just realised you have your inputs in your physics process. The above was for the _input(event) like this:

func _input(event):
	if event.is_action_pressed("sprint"):
		move_speed = 16
	elif event.is_action_released("sprint"):
		move_speed = 8

But you can change the format to be more like your original code:

if Input.is_action_pressed("sprint"):
    move_speed = 16
elif Input.is_action_just_released("sprint"):
    move_speed = 8

PS I would suggest you move all your inputs into the input event block and keep them all together in one place.

1 Like

Ah, thank you so much that last bit worked perfectly, I just need to fix the animations & sound now! I will rework my script to get the inputs all grouped together, honestly got a little messy there!

1 Like