diff --git a/3-rd-person-camera/.editorconfig b/3-rd-person-camera/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/3-rd-person-camera/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/3-rd-person-camera/.gitattributes b/3-rd-person-camera/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/3-rd-person-camera/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/3-rd-person-camera/.gitignore b/3-rd-person-camera/.gitignore new file mode 100644 index 0000000..0af181c --- /dev/null +++ b/3-rd-person-camera/.gitignore @@ -0,0 +1,3 @@ +# Godot 4+ specific ignores +.godot/ +/android/ diff --git a/3-rd-person-camera/Player.tscn b/3-rd-person-camera/Player.tscn new file mode 100644 index 0000000..3099a68 --- /dev/null +++ b/3-rd-person-camera/Player.tscn @@ -0,0 +1,66 @@ +[gd_scene format=3 uid="uid://crtm0xtiql3r8"] + +[ext_resource type="Script" uid="uid://bn777gguclud5" path="res://player.gd" id="1_xhfnw"] +[ext_resource type="Script" uid="uid://b4td4k8yo5y78" path="res://camera_spring_arm.gd" id="2_kpjcp"] +[ext_resource type="Script" uid="uid://b720l6m0ehrj3" path="res://camera_follow.gd" id="3_kne1u"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_xhfnw"] +size = Vector3(1, 1.4072266, 1) + +[sub_resource type="BoxMesh" id="BoxMesh_0rwas"] + +[sub_resource type="SphereShape3D" id="SphereShape3D_kne1u"] +radius = 0.3 + +[node name="Player" type="CharacterBody3D" unique_id=165510044] +script = ExtResource("1_xhfnw") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1104396769] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.20361328, 0) +shape = SubResource("BoxShape3D_xhfnw") + +[node name="CubeGuy" type="Node3D" parent="." unique_id=1651396216] + +[node name="MeshInstance3D" type="MeshInstance3D" parent="CubeGuy" unique_id=367855086] +mesh = SubResource("BoxMesh_0rwas") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="CubeGuy" unique_id=1565560527] +transform = Transform3D(0.22778136, 0, 0, 0, 0.4572928, 0, 0, 0, 0.2800231, 0.36544353, -0.65451574, 0) +mesh = SubResource("BoxMesh_0rwas") + +[node name="MeshInstance3D3" type="MeshInstance3D" parent="CubeGuy" unique_id=2097296241] +transform = Transform3D(0.22778136, 0, 0, 0, 0.4572928, 0, 0, 0, 0.2800231, -0.38543648, -0.65451574, 0) +mesh = SubResource("BoxMesh_0rwas") + +[node name="MeshInstance3D4" type="MeshInstance3D" parent="CubeGuy" unique_id=383816037] +transform = Transform3D(0.14033328, 0.3601992, 0, -0.17941824, 0.28173247, 0, 0, 0, 0.28002307, -0.60614854, -0.07838535, 0) +mesh = SubResource("BoxMesh_0rwas") + +[node name="MeshInstance3D5" type="MeshInstance3D" parent="CubeGuy" unique_id=326472138] +transform = Transform3D(-0.14033328, -0.3601992, 2.4480395e-08, -0.17941824, 0.28173247, 0, -1.2268325e-08, -3.1489616e-08, -0.28002307, 0.6122027, -0.07838535, 0) +mesh = SubResource("BoxMesh_0rwas") + +[node name="MeshInstance3D6" type="MeshInstance3D" parent="CubeGuy" unique_id=1642768377] +transform = Transform3D(-0.113692805, 0, -2.4480393e-08, 0, 0.11736439, 0, 9.939342e-09, 0, -0.28002304, -0.26236355, 0.3103568, 0.42819703) +mesh = SubResource("BoxMesh_0rwas") + +[node name="MeshInstance3D7" type="MeshInstance3D" parent="CubeGuy" unique_id=695468518] +transform = Transform3D(-0.113692805, 0, -2.4480393e-08, 0, 0.11736439, 0, 9.939342e-09, 0, -0.28002304, 0.2908606, 0.28320956, 0.42819703) +mesh = SubResource("BoxMesh_0rwas") + +[node name="SpringArmPivot" type="Node3D" parent="." unique_id=1671817680] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.22, 0) +script = ExtResource("2_kpjcp") + +[node name="SpringArm3D" type="SpringArm3D" parent="SpringArmPivot" unique_id=141439848] +collision_mask = 2 +shape = SubResource("SphereShape3D_kne1u") +spring_length = 7.0 + +[node name="SpringPosition" type="Node3D" parent="SpringArmPivot/SpringArm3D" unique_id=1307131677] + +[node name="Camera3D" type="Camera3D" parent="SpringArmPivot" unique_id=1120161087 node_paths=PackedStringArray("spring_arm")] +keep_aspect = 0 +script = ExtResource("3_kne1u") +spring_arm = NodePath("../SpringArm3D/SpringPosition") +lerp_power = 6.0 diff --git a/3-rd-person-camera/camera_follow.gd b/3-rd-person-camera/camera_follow.gd new file mode 100644 index 0000000..95d5b13 --- /dev/null +++ b/3-rd-person-camera/camera_follow.gd @@ -0,0 +1,9 @@ +extends Camera3D + + +@export var spring_arm: Node3D +@export var lerp_power: float = 1.0 + + +func _process(delta: float) -> void: + position = lerp(position, spring_arm.position, delta * lerp_power) diff --git a/3-rd-person-camera/camera_follow.gd.uid b/3-rd-person-camera/camera_follow.gd.uid new file mode 100644 index 0000000..d50d605 --- /dev/null +++ b/3-rd-person-camera/camera_follow.gd.uid @@ -0,0 +1 @@ +uid://b720l6m0ehrj3 diff --git a/3-rd-person-camera/camera_spring_arm.gd b/3-rd-person-camera/camera_spring_arm.gd new file mode 100644 index 0000000..0730c7a --- /dev/null +++ b/3-rd-person-camera/camera_spring_arm.gd @@ -0,0 +1,31 @@ +extends Node3D + + +@export var mouse_sensitivity: float = 0.005 +@export_range(-90.0, 0.0, 0.1, "radians_as_degrees") var min_vertical_angle: float = -PI/2 +@export_range(0.0, 90.0, 0.1, "radians_as_degrees") var max_vertical_angle: float = PI/4 + +@onready var spring_arm := $SpringArm3D + +func _ready() -> void: + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + + +func _unhandled_input(event : InputEvent) -> void: + if event is InputEventMouseMotion: + rotation.y -= event.relative.x * mouse_sensitivity + rotation.y = wrapf(rotation.y, 0.0, TAU) + + rotation.x -= event.relative.y * mouse_sensitivity + rotation.x = clamp(rotation.x, min_vertical_angle, max_vertical_angle) + + if event.is_action_pressed("wheel_up"): + spring_arm.spring_length -=1 + if event.is_action_pressed("wheel_down"): + spring_arm.spring_length +=1 + + if event.is_action_pressed("toggle_mouse_capture"): + if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + else: + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) diff --git a/3-rd-person-camera/camera_spring_arm.gd.uid b/3-rd-person-camera/camera_spring_arm.gd.uid new file mode 100644 index 0000000..968c3e9 --- /dev/null +++ b/3-rd-person-camera/camera_spring_arm.gd.uid @@ -0,0 +1 @@ +uid://b4td4k8yo5y78 diff --git a/3-rd-person-camera/icon.svg b/3-rd-person-camera/icon.svg new file mode 100644 index 0000000..c6bbb7d --- /dev/null +++ b/3-rd-person-camera/icon.svg @@ -0,0 +1 @@ + diff --git a/3-rd-person-camera/icon.svg.import b/3-rd-person-camera/icon.svg.import new file mode 100644 index 0000000..fd59468 --- /dev/null +++ b/3-rd-person-camera/icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bfmv1klwerreo" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/3-rd-person-camera/player.gd b/3-rd-person-camera/player.gd new file mode 100644 index 0000000..acb7fb2 --- /dev/null +++ b/3-rd-person-camera/player.gd @@ -0,0 +1,28 @@ +extends CharacterBody3D + + +const SPEED = 5.0 +const JUMP_VELOCITY = 4.5 + + +func _physics_process(delta: float) -> void: + # Add the gravity. + if not is_on_floor(): + velocity += get_gravity() * delta + + # Handle jump. + if Input.is_action_just_pressed("ui_accept") and is_on_floor(): + velocity.y = JUMP_VELOCITY + + # Get the input direction and handle the movement/deceleration. + # As good practice, you should replace UI actions with custom gameplay actions. + var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") + var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() + 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) + + move_and_slide() diff --git a/3-rd-person-camera/player.gd.uid b/3-rd-person-camera/player.gd.uid new file mode 100644 index 0000000..00f7d15 --- /dev/null +++ b/3-rd-person-camera/player.gd.uid @@ -0,0 +1 @@ +uid://bn777gguclud5 diff --git a/3-rd-person-camera/project.godot b/3-rd-person-camera/project.godot new file mode 100644 index 0000000..0aabc5b --- /dev/null +++ b/3-rd-person-camera/project.godot @@ -0,0 +1,41 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="3rd_person_camera" +config/features=PackedStringArray("4.6", "Forward Plus") +config/icon="res://icon.svg" + +[input] + +wheel_up={ +"deadzone": 0.2, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":8,"position":Vector2(726, 8),"global_position":Vector2(735, 56),"factor":1.0,"button_index":4,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} +wheel_down={ +"deadzone": 0.2, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(400, 21),"global_position":Vector2(409, 69),"factor":1.0,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} +toggle_mouse_capture={ +"deadzone": 0.2, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":4,"position":Vector2(461, 22),"global_position":Vector2(470, 70),"factor":1.0,"button_index":3,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} + +[physics] + +3d/physics_engine="Jolt Physics" + +[rendering] + +rendering_device/driver.windows="d3d12" diff --git a/3-rd-person-camera/scene.tscn b/3-rd-person-camera/scene.tscn new file mode 100644 index 0000000..c5b41d2 --- /dev/null +++ b/3-rd-person-camera/scene.tscn @@ -0,0 +1,30 @@ +[gd_scene format=3 uid="uid://b7afbx36ltb3f"] + +[ext_resource type="PackedScene" uid="uid://crtm0xtiql3r8" path="res://Player.tscn" id="1_ulcgi"] + +[sub_resource type="BoxMesh" id="BoxMesh_nxogm"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_ulcgi"] + +[node name="scene" type="Node3D" unique_id=22320312] + +[node name="Player" parent="." unique_id=165510044 instance=ExtResource("1_ulcgi")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.3040223, 0) + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=818712731] +transform = Transform3D(0.030703627, 0.98235905, -0.18446636, -0.1612905, 0.18700416, 0.9690277, 0.9864293, -1.2735805e-08, 0.16418687, -4.08134, 0.3070748, 0.97087634) +shadow_enabled = true + +[node name="Node3D" type="Node3D" parent="." unique_id=1081100876] +transform = Transform3D(3.5710833, 0, 0, 0, 1, 0, 0, 0, 2.2964425, 0, 0, 0) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D" unique_id=1193968330] +transform = Transform3D(7.6892195, 0, 0, 0, 0.34217757, 0, 0, 0, 8.638922, 0, 0, 0) +mesh = SubResource("BoxMesh_nxogm") + +[node name="StaticBody3D" type="StaticBody3D" parent="Node3D" unique_id=2072095624] +transform = Transform3D(1.0000001, 0, 0, 0, 1.0000001, 0, 0, 0, 1.0000001, 0, 0, 0) + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Node3D/StaticBody3D" unique_id=1444198204] +transform = Transform3D(7.6892185, 0, 0, 0, 0.34217754, 0, 0, 0, 8.638921, 0, 0, 0) +shape = SubResource("BoxShape3D_ulcgi") diff --git a/Making a GOOD third person camera in Godot 4 - YouTube.url b/Making a GOOD third person camera in Godot 4 - YouTube.url new file mode 100644 index 0000000..fa52f18 --- /dev/null +++ b/Making a GOOD third person camera in Godot 4 - YouTube.url @@ -0,0 +1,2 @@ +[InternetShortcut] +URL=https://www.youtube.com/watch?v=ZCb12AHKMfE