Hi! I’m following a Godot tutorial and running into a problem. In my code, the player doesn’t move continuously when I hold the “forward” button. If I press it briefly, the player moves only a little, and if I press it again, they move a little more. However, holding the button doesn’t result in continuous movement.
Also, if I set the acceleration to anything above 2, like 2.1 or 2.001, the player starts accelerating forever and eventually moves out of the world.
Could anyone help me figure out what’s going wrong?
extends CharacterBody3D
@onready var player_mesh = get_node("Knight")
@onready var camera_h = get_node("cameraroot/horizontal")
@export var gravity: float = 9.8
@export var jump_force: int = 9
@export var walk_speed: int = 3
@export var run_speed: int = 10
var idle_node_name: String = "Idle"
var walk_node_name: String = "Walk"
var run_node_name: String = "Run"
var jump_node_name: String = "Jump"
var attack1_node_name: String = "Attack1"
var death_node_name: String = "Death"
var is_attacking: bool
var is_walking: bool
var is_running: bool
var is_dying: bool
var direction: Vector3
var horizontal_velocity: Vector3
var aim_turn: float
var movement: Vector3
var vertical_velocity: Vector3
var movement_speed: int
var angular_acceleration: float
var acceleration: float
var just_hit: bool
func _ready() -> void:
pass
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
aim_turn = -event.relative.x * 0.015
if event.is_action_pressed("aim"):
direction = camera_h.global_transform.basis.z
func _physics_process(delta: float) -> void:
var on_floor = is_on_floor()
if !is_dying:
if !on_floor:
vertical_velocity += Vector3.DOWN*gravity*2*delta
else:
vertical_velocity = Vector3.DOWN*gravity/10
if Input.is_action_just_pressed("jump") and (!is_attacking) and on_floor:
vertical_velocity = Vector3.UP*jump_force
angular_acceleration = 10
movement_speed = 0
acceleration = 2.00
var h_rot = camera_h.global_transform.basis.get_euler().y
if (Input.is_action_just_pressed("forward") || Input.is_action_just_pressed("backward") || Input.is_action_just_pressed("left") || Input.is_action_just_pressed("right")):
direction = Vector3(Input.get_action_strength("left") - Input.get_action_strength("right"),
0,
Input.get_action_strength("forward") - Input.get_action_strength("backward"))
direction = direction.rotated(Vector3.UP, h_rot).normalized()
if Input.is_action_pressed("sprint") and (is_walking):
movement_speed = run_speed
is_running = true
else:
is_walking = true
movement_speed = walk_speed
else:
is_walking = false
is_running = false
if Input.is_action_pressed("aim"):
player_mesh.rotation.y = lerp_angle(player_mesh.rotation.y, camera_h.rotation.y, delta*angular_acceleration)
else:
player_mesh.rotation.y = lerp_angle(player_mesh.rotation.y, atan2(direction.x, direction.z) - rotation.y, delta * angular_acceleration)
if is_attacking:
horizontal_velocity = horizontal_velocity.lerp(direction.normalized() * 0.1, acceleration)
else:
horizontal_velocity = horizontal_velocity.lerp(direction.normalized() * movement_speed, acceleration)
velocity.z = horizontal_velocity.z
velocity.y = vertical_velocity.y
velocity.x = horizontal_velocity.x
move_and_slide()
The weight for lerp() (your acceleration) should be between 0 and 1. And 1 means it will reach it’s target in 1 frame, so it should be less then that if you want acceleration. More than 1 will make it overshoot it’s target value. Usually it’s used with delta.
If you use delta as weight for lerp it will reach the taret value in one second. 0.5 * delta will be half as fast, so it’ll reach the target value in 2 seconds, ect…
Clamp the acceleration value: Ensure that acceleration remains within a reasonable range, such as between 0 and 2.00.
Use a maximum velocity: Set a maximum speed for the player and prevent them from exceeding it.
Adjust Acceleration Based on Movement:
Reduce acceleration when moving towards a target: If the player is moving towards a specific point or enemy, gradually decrease acceleration as they get closer.
Increase acceleration when moving away from a target: Increase acceleration when the player is moving away from a target, encouraging them to catch up.
Implement a Deceleration Mechanism:
Apply a deceleration force: When the player releases the movement keys, introduce a deceleration force to slow them down gradually.
Use a friction coefficient: Simulate friction between the player and the ground to gradually reduce their speed.
Revised Code Example:
Here’s a revised version of the _physics_process function with a limited acceleration and a deceleration mechanism: