Godot Version
4.3
Question
There is a problem. When I rotate the mouse very much, my character starts walking strangely. Pressing one of the WASD buttons, for some reason, he walks diagonally.
NORMAL WALK
PROBLEM
Player.gd
extends Unit
@onready var head = $Head
@export var VelocityComponent : _VelocityComponent
@export var ControllerComponent : _ControllerComponent
var bullet = preload("res://scenes/Player/Weapons/bullet.tscn")
const MAX_WALL_SLIDING = 3
enum {
NOT_TOUCH = 0,
TOUCH = 1
}
var wall_touch := 0 :
set(value):
wall_touch = value
print(wall_touch)
func _ready() -> void:
ControllerComponent.Camera = $Head/Camera3D
ControllerComponent.Head = head
VelocityComponent.ControllerComponent = ControllerComponent
func _physics_process(delta: float) -> void:
VelocityComponent.Move(self)
if is_on_floor():
wall_touch = NOT_TOUCH
func _on_wall_sliding_wall_touch() -> void:
wall_touch += TOUCH
func _on_controller_component_shooting() -> void:
var instance = bullet.instantiate()
instance.position = $Head/Camera3D/Revolver/RayCast3D.global_position
instance.transform.basis = $Head/Camera3D/Revolver/RayCast3D.global_transform.basis
get_parent().add_child(instance)
VelocityComponent.gd
extends Node
class_name _VelocityComponent
@onready var TimerStamina := $RecoverStamina
var ControllerComponent : _ControllerComponent
var Velocity : Vector3
var TransformBasis : Basis
var SPEED : int
var Player : Unit
var direction := Vector3.ZERO
const WALL_FRICTION = 0.5
const FLY_MOVE_MULTIPLIER = 10.0 ### Чем больше, тем больше управление в воздухе. Влияет на рывок в воздухе
@export var DASH_MULTIPLIER := 10
@export var jump_height : float
@export var jump_time_to_peak : float
@export var jump_time_to_descent : float
@onready var jump_velocity : float = (2.0 * jump_height) / jump_time_to_peak
@onready var jump_gravity : float = (-2.0 * jump_height) / (jump_time_to_peak * jump_time_to_peak)
@onready var fall_gravity : float = (-2.0 * jump_height) / (jump_time_to_descent * jump_time_to_descent)
func _physics_process(delta: float) -> void:
var input_dir := ControllerComponent.input_dir
direction = (TransformBasis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if Player.is_on_floor():
if direction:
Velocity.x = direction.x * SPEED
Velocity.z = direction.z * SPEED
else:
Velocity.x = move_toward(Velocity.x, 0, SPEED)
Velocity.z = move_toward(Velocity.z, 0, SPEED)
else:
## Плавное замеддение в воздухе
Velocity.x = lerp(Velocity.x, direction.x*SPEED,delta * FLY_MOVE_MULTIPLIER)
Velocity.z = lerp(Velocity.z, direction.z*SPEED,delta * FLY_MOVE_MULTIPLIER)
if !Player.is_on_floor():
Velocity.y += Gravity() * delta
else:
### Если не обнулять, накопиться большое значение и падение будет слишком резким
Velocity.y = 0
Friction()
func RecoverStamina():
if Player.stamina < Player.MAX_STAMINA:
Player.stamina += Player.COUNT_RECOVER_STAMINA
TimerStamina.start()
func WasteStamina(num : int):
if Player.stamina > Player.MIN_STAMINA:
Player.stamina -= num
TimerStamina.start()
func Jump():
if Player.stamina > Player.MIN_STAMINA:
if Player.is_on_floor():
Velocity.y = jump_velocity
if !Player.is_on_floor() and Player.is_on_wall():
Velocity = Player.get_wall_normal() * jump_velocity
Velocity.y = jump_velocity
func Dash():
### Рывок с места
if Player.stamina > Player.MIN_STAMINA and !direction:
Velocity.x = -TransformBasis.z.x * SPEED * DASH_MULTIPLIER
Velocity.z = -TransformBasis.z.z * SPEED * DASH_MULTIPLIER
### Рывок в движении
elif Player.stamina > Player.MIN_STAMINA and direction:
Velocity.x = direction.x * SPEED * DASH_MULTIPLIER
Velocity.z = direction.z * SPEED * DASH_MULTIPLIER
func Gravity() -> float:
return jump_gravity if Velocity.y > 0.0 else fall_gravity
func Friction():
if Player.is_on_wall() and !Player.is_on_floor():
if Player.wall_touch <= Player.MAX_WALL_SLIDING:
Velocity.y *= WALL_FRICTION
func Move(player : Unit):
Player = player
player.velocity = Velocity
TransformBasis = player.head.transform.basis
SPEED = player.speed
player.move_and_slide()
ControllerComponent.gd
extends Node
class_name _ControllerComponent
signal waste_stamina
signal dash
signal jump
signal sliding
signal shooting
@export var SENS := 0.02
var input_dir : Vector2
var Head
var Camera : Camera3D
enum Actions {
DASH = 1,
JUMP = 1,
SLIDING = 1
}
func _physics_process(delta: float) -> void:
input_dir = Input.get_vector("Left", "Right", "Forward", "Back")
Camera.rotation.z = -input_dir.x * deg_to_rad(2)
func _input(event: InputEvent) -> void:
if event is InputEventMouse:
if event is InputEventMouseMotion:
Head.rotate_y(-event.relative.x * SENS)
Camera.rotate_x(-event.relative.y * SENS)
Camera.rotation.x = clamp(Camera.rotation.x, deg_to_rad(-40),deg_to_rad(50))
if event is InputEventMouseButton:
if event.is_action_pressed("Shoot"):
shooting.emit()
if event is InputEventKey:
### Сначала сигнал действия, потом трата выносливости !!!
if event.is_action_pressed("Dash"):
dash.emit()
waste_stamina.emit(Actions.DASH)
if event.is_action_pressed("Jump"):
jump.emit()
waste_stamina.emit(Actions.JUMP)
if event.is_action_pressed("Sliding"):
sliding.emit()
waste_stamina.emit(Actions.SLIDING)