extends CharacterBody3D class_name Character @export_group("Movement Settings") @export var normal_speed: float = 6.0 @export var sprint_speed: float = 10.0 @export var jump_velocity: float = 10.0 @export var gravity_scale: float = 1.0 @export var rotation_speed: float = 10.0 @export var acceleration: float = 10.0 # Сила ускорения @export var deceleration: float = 8.0 # Сила замедления @export_group("References") @export var body: Node3D = null @export var spring_arm_offset: Node3D = null @export var respawn_point: Vector3 = Vector3(0, 5, 0) var _current_speed: float var _target_velocity: Vector3 = Vector3.ZERO # Целевая скорость var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") var _has_input: bool = false var _can_sprint: bool = true func _ready(): $SpringArmOffset/SpringArm3D/Camera3D.current = false func _physics_process(delta): # Обработка гравитации if not is_on_floor(): velocity.y -= gravity * delta _can_sprint = false # В воздухе нельзя ускоряться else: _can_sprint = true # На земле можно ускоряться # Обработка прыжка if is_on_floor() and Input.is_action_just_pressed("jump"): velocity.y = jump_velocity _can_sprint = false # При прыжке сразу отключаем спринт _move(delta) move_and_slide() if body and body.has_method("animate"): body.animate(velocity) func _process(_delta): _check_fall_and_respawn() func _move(delta: float) -> void: var input_direction = Input.get_vector("move_left", "move_right", "move_forward", "move_backward") _has_input = input_direction.length() > 0.1 # Получаем направление движения относительно камеры var camera_basis = $SpringArmOffset/SpringArm3D/Camera3D.global_transform.basis var direction = (camera_basis * Vector3(input_direction.x, 0, input_direction.y)).normalized() _update_speed() if direction: # Устанавливаем целевую скорость с учетом направления _target_velocity.x = direction.x * _current_speed _target_velocity.z = direction.z * _current_speed # Плавно изменяем скорость в сторону целевой velocity.x = lerp(velocity.x, _target_velocity.x, acceleration * delta) velocity.z = lerp(velocity.z, _target_velocity.z, acceleration * delta) # Поворачиваем тело персонажа в направлении движения if velocity.length() > 0.1: var target_rotation = atan2(_target_velocity.x, _target_velocity.z) body.rotation.y = lerp_angle(body.rotation.y, target_rotation, rotation_speed * delta) else: # Если нет ввода, плавно уменьшаем скорость _target_velocity = Vector3.ZERO velocity.x = lerp(velocity.x, 0.0, deceleration * delta) velocity.z = lerp(velocity.z, 0.0, deceleration * delta) func is_running() -> bool: return Input.is_action_pressed("shift") and _current_speed == sprint_speed func _update_speed() -> void: # Ускорение работает только когда персонаж на земле if _can_sprint and Input.is_action_pressed("shift"): _current_speed = sprint_speed else: _current_speed = normal_speed func _check_fall_and_respawn(): if global_transform.origin.y < -15.0: _respawn() func _respawn(): global_transform.origin = respawn_point velocity = Vector3.ZERO _target_velocity = Vector3.ZERO _can_sprint = true