Can anybody help me out with this? I've got my player to move on a grid using snapped. He can walk up ramps and gravity is applied with move_and_slide() (although going up ramps is a bit choppy.) What I'm stumped on is trying to get the player to turn smoothly. When I use lerp_angle it doesnt work. If the character is facing left for example, and you hit right, he should turn and then you can begin walking right after the turn is completed. So a tap on the input would face you the direction you want to move without moving you, unless youre already facing that direction.
extends CharacterBody3D
var walk_speed = 4.0
var turn_speed = 4.0
var angular_speed = 5.0
var pos = Vector3(0, position.y, 0)
var new_pos = Vector3(0, position.y, 0)
var is_moving = false
var percent_moved = 0.0
var percent_rotated = 0.0
var gravity = 15.0
var hover_strength = 0.5
var max_fall_speed = -10.0
@export var locomotionStatePlaybackPath: String;
@export var locomotionBlendPath: String;
@export var jumpOneShotPlayback: String;
@onready var ray = $RayCast3D
@onready var player_body = $rig
@onready var anim = $AnimationTree
#@onready var animplayer = $AnimationPlayer
@onready var camera = get_node("Camera3D")
enum PlayerState {IDLE, TURNING, WALKING, JUMPING, HOVERING, FALLING, DOUBLEJUMPING}
enum FacingDirection {UP, DOWN, LEFT, RIGHT}
var player_state = PlayerState.IDLE
var facing_direction = FacingDirection.UP
func _ready():
pos = position
func _physics_process(delta):
print(position.y)
pos = pos.snapped(Vector3(0.5,position.y,0.5))
if player_state == PlayerState.TURNING:
return
elif is_moving == false:
process_input(delta)
elif new_pos != Vector3.ZERO:
move(delta)
else:
anim.travel("Idle")
is_moving = false
velocity.y -= gravity * delta
var move_velocity = Vector2(velocity.x, velocity.z)
var normalized_velocity = move_velocity.length() / walk_speed
move_and_slide()
if Input.is_action_just_pressed("ui_cancel"):
get_tree().quit()
func process_input(delta):
if new_pos.z == 0:
new_pos.x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
if new_pos.x == 0:
new_pos.z = int(Input.is_action_pressed("ui_down")) - int(Input.is_action_pressed("ui_up"))
if new_pos != Vector3.ZERO:
if need_to_turn():
player_state = PlayerState.TURNING
turn(delta)
else:
pos = position
is_moving = true
func need_to_turn():
var new_facing_direction
if new_pos.x < 0:
new_facing_direction = FacingDirection.LEFT
if new_pos.x > 0:
new_facing_direction = FacingDirection.RIGHT
if new_pos.z < 0:
new_facing_direction = FacingDirection.UP
if new_pos.z > 0:
new_facing_direction = FacingDirection.DOWN
if facing_direction != new_facing_direction:
facing_direction = new_facing_direction
return true
facing_direction = new_facing_direction
return false
func turn(delta):
percent_rotated += turn_speed * delta
if percent_moved >= 1.0:
percent_rotated = 0.0
else:
if new_pos.x < 0:
player_body.rotation.y = 3 * PI / 2
player_state = PlayerState.IDLE
elif new_pos.x > 0:
player_body.rotation.y = PI / 2
await get_tree().create_timer(0.5).timeout
player_state = PlayerState.IDLE
elif new_pos.z < 0:
player_body.rotation.y = PI
await get_tree().create_timer(0.5).timeout
player_state = PlayerState.IDLE
elif new_pos.z > 0:
player_body.rotation.y = 0
await get_tree().create_timer(0.5).timeout
player_state = PlayerState.IDLE
func move(delta):
percent_moved += walk_speed * delta
if percent_moved >= 1.0:
position = pos + new_pos
percent_moved = 0.0
is_moving = false
else:
position = pos + (new_pos * percent_moved)