diff --git a/materials/level.tres b/materials/level.tres new file mode 100644 index 0000000..29f5a19 --- /dev/null +++ b/materials/level.tres @@ -0,0 +1,4 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://dv185w3f5gjp4"] + +[resource] +albedo_color = Color(0.230315, 0.230315, 0.230315, 1) diff --git a/scenes/godot_plush_model.tscn b/scenes/godot_plush_model.tscn new file mode 100644 index 0000000..fe28084 --- /dev/null +++ b/scenes/godot_plush_model.tscn @@ -0,0 +1,5 @@ +[gd_scene load_steps=2 format=3 uid="uid://b4ixstqw06c4y"] + +[ext_resource type="PackedScene" uid="uid://cg7of11dls47q" path="res://scenes/godot_plush_model.glb" id="1_fn30i"] + +[node name="godot_plush_model" instance=ExtResource("1_fn30i")] diff --git a/scenes/level.tscn b/scenes/level.tscn index c779977..b54ce04 100644 --- a/scenes/level.tscn +++ b/scenes/level.tscn @@ -1,29 +1,45 @@ -[gd_scene load_steps=5 format=3 uid="uid://8ywbh7j4mmai"] +[gd_scene load_steps=6 format=3 uid="uid://8ywbh7j4mmai"] [ext_resource type="PackedScene" uid="uid://dsrbro31ggv7u" path="res://scenes/player.tscn" id="1_2q6dc"] +[ext_resource type="Material" uid="uid://dv185w3f5gjp4" path="res://materials/level.tres" id="2_w7c3h"] -[sub_resource type="PlaneMesh" id="PlaneMesh_rd3vj"] +[sub_resource type="Environment" id="Environment_2q6dc"] -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_w7c3h"] -albedo_color = Color(5.41471e-08, 0.281997, 1.44392e-07, 1) +[sub_resource type="BoxMesh" id="BoxMesh_2q6dc"] -[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_2q6dc"] +[sub_resource type="BoxMesh" id="BoxMesh_w7c3h"] [node name="level" type="Node3D"] -[node name="StaticBody3D" type="StaticBody3D" parent="."] - -[node name="MeshInstance3D" type="MeshInstance3D" parent="StaticBody3D"] -transform = Transform3D(10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0) -mesh = SubResource("PlaneMesh_rd3vj") -skeleton = NodePath("../..") -surface_material_override/0 = SubResource("StandardMaterial3D_w7c3h") - -[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"] -shape = SubResource("WorldBoundaryShape3D_2q6dc") - [node name="Player" parent="." instance=ExtResource("1_2q6dc")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0640043, 0.486621, -0.407444) +jump_velocity = 7.0 [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 4, -1) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_2q6dc") + +[node name="CSGMesh3D" type="CSGMesh3D" parent="."] +transform = Transform3D(38.6121, 0, 0, 0, 0.894564, 0, 0, 0, 34.4712, 0, 0, 0) +use_collision = true +mesh = SubResource("BoxMesh_2q6dc") + +[node name="CSGMesh3D2" type="CSGMesh3D" parent="."] +transform = Transform3D(1.00624, 0, 0, 0, 1.00624, 0, 0, 0, 1.00624, -0.146904, 1.43323, 3.63201) +use_collision = true +mesh = SubResource("BoxMesh_w7c3h") +material = ExtResource("2_w7c3h") + +[node name="CSGMesh3D3" type="CSGMesh3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.293807, 2.86646, 6.43488) +use_collision = true +mesh = SubResource("BoxMesh_w7c3h") +material = ExtResource("2_w7c3h") + +[node name="CSGMesh3D4" type="CSGMesh3D" parent="."] +transform = Transform3D(13.2076, 0, 0, 0, 1, 0, 0, 0, 1, -0.587614, 4.46185, 8.71996) +use_collision = true +mesh = SubResource("BoxMesh_w7c3h") +material = ExtResource("2_w7c3h") diff --git a/scenes/level.tscn5923790033.tmp b/scenes/level.tscn5923790033.tmp new file mode 100644 index 0000000..b309fcd --- /dev/null +++ b/scenes/level.tscn5923790033.tmp @@ -0,0 +1,44 @@ +[gd_scene load_steps=6 format=3 uid="uid://8ywbh7j4mmai"] + +[ext_resource type="PackedScene" uid="uid://dsrbro31ggv7u" path="res://scenes/player.tscn" id="1_2q6dc"] +[ext_resource type="Material" uid="uid://dv185w3f5gjp4" path="res://materials/level.tres" id="2_w7c3h"] + +[sub_resource type="Environment" id="Environment_2q6dc"] + +[sub_resource type="BoxMesh" id="BoxMesh_2q6dc"] + +[sub_resource type="BoxMesh" id="BoxMesh_w7c3h"] + +[node name="level" type="Node3D"] + +[node name="Player" parent="." instance=ExtResource("1_2q6dc")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0640043, 0.486621, -0.407444) + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 4, -1) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_2q6dc") + +[node name="CSGMesh3D" type="CSGMesh3D" parent="."] +transform = Transform3D(38.6121, 0, 0, 0, 0.894564, 0, 0, 0, 34.4712, 0, 0, 0) +use_collision = true +mesh = SubResource("BoxMesh_2q6dc") + +[node name="CSGMesh3D2" type="CSGMesh3D" parent="."] +transform = Transform3D(1.00624, 0, 0, 0, 1.00624, 0, 0, 0, 1.00624, -0.146904, 1.43323, 3.63201) +use_collision = true +mesh = SubResource("BoxMesh_w7c3h") +material = ExtResource("2_w7c3h") + +[node name="CSGMesh3D3" type="CSGMesh3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.293807, 2.86646, 6.43488) +use_collision = true +mesh = SubResource("BoxMesh_w7c3h") +material = ExtResource("2_w7c3h") + +[node name="CSGMesh3D4" type="CSGMesh3D" parent="."] +transform = Transform3D(13.2076, 0, 0, 0, 1, 0, 0, 0, 1, -0.587614, 4.46185, 8.71996) +use_collision = true +mesh = SubResource("BoxMesh_w7c3h") +material = ExtResource("2_w7c3h") diff --git a/scripts/3d_godot_robot.gd b/scripts/3d_godot_robot.gd index 177404f..24e6603 100644 --- a/scripts/3d_godot_robot.gd +++ b/scripts/3d_godot_robot.gd @@ -7,22 +7,29 @@ const LERP_VELOCITY: float = 0.15 @export var _character: CharacterBody3D = null @export var animation_player: AnimationPlayer = null -func animate(_velocity: Vector3) -> void: +func animate(velocity: Vector3) -> void: if not _character.is_on_floor(): - if _velocity.y < 0: + if velocity.y < 0: animation_player.play("fall") else: animation_player.play("up") return - if _velocity.length() > 0.1: # Если есть движение + # Используем _has_input вместо проверки длины скорости + if _character._has_input: if _character.is_running(): - animation_player.play("run") # Спринт + animation_player.play("run") else: - animation_player.play("walk") # Обычная ходьба + animation_player.play("walk") return - animation_player.play("idle") # Бездействие + # Плавное переключение на idle при инерции + if velocity.length() > 0.5: # Небольшой порог для плавного перехода + var current_anim = animation_player.current_animation + if current_anim != "walk" and current_anim != "run": + animation_player.play("walk", 0.1) # Плавный переход с blend_time 0.1 сек + else: + animation_player.play("idle", 0.2) # Плавный переход на idle @rpc("any_peer", "reliable") func sync_player_rotation(rotation_y: float) -> void: diff --git a/scripts/player.gd b/scripts/player.gd index 0b50857..fa72293 100644 --- a/scripts/player.gd +++ b/scripts/player.gd @@ -5,8 +5,10 @@ class_name Character @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 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 @@ -14,24 +16,28 @@ class_name Character @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): - var current_scene = get_tree().get_current_scene() - +func _physics_process(delta): + # Обработка гравитации if not is_on_floor(): velocity.y -= gravity * delta - - if is_on_floor(): - if Input.is_action_just_pressed("jump"): - velocity.y = jump_velocity + _can_sprint = false # В воздухе нельзя ускоряться else: - velocity.y -= gravity * delta + _can_sprint = true # На земле можно ускоряться - _move() + # Обработка прыжка + 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"): @@ -40,13 +46,9 @@ func _physics_process(delta): func _process(_delta): _check_fall_and_respawn() -func freeze(): - velocity.x = 0 - velocity.z = 0 - _current_speed = 0 - -func _move() -> void: +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 @@ -55,23 +57,33 @@ func _move() -> void: _update_speed() if direction: - velocity.x = direction.x * _current_speed - velocity.z = direction.z * _current_speed + # Устанавливаем целевую скорость с учетом направления + _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(velocity.x, velocity.z) - body.rotation.y = lerp_angle(body.rotation.y, target_rotation, rotation_speed * get_process_delta_time()) - + 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: - velocity.x = move_toward(velocity.x, 0, _current_speed) - velocity.z = move_toward(velocity.z, 0, _current_speed) + # Если нет ввода, плавно уменьшаем скорость + _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: - _current_speed = sprint_speed if Input.is_action_pressed("shift") else normal_speed + # Ускорение работает только когда персонаж на земле + 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: @@ -80,3 +92,5 @@ func _check_fall_and_respawn(): func _respawn(): global_transform.origin = respawn_point velocity = Vector3.ZERO + _target_velocity = Vector3.ZERO + _can_sprint = true