├── .gitignore ├── LICENSE ├── Physics └── player.tres ├── README.md ├── Scenes ├── cuberb.gd └── scene1.tscn ├── Scripts ├── Draw3D.gd ├── DrawLine3D.gd └── draw.gd ├── Textures ├── TexturesCom_Pavement_CobblestoneMossy01_2x2_1K_albedo.png ├── TexturesCom_Pavement_CobblestoneMossy01_2x2_1K_albedo.png.import ├── TexturesCom_RoughWoodPlanks_2x2_1K_albedo.png └── TexturesCom_RoughWoodPlanks_2x2_1K_albedo.png.import ├── addons └── godot-jolt │ ├── LICENSE.txt │ ├── THIRDPARTY.txt │ ├── godot-jolt.gdextension │ ├── linux │ ├── godot-jolt_linux-x64.so │ ├── godot-jolt_linux-x64_editor.so │ ├── godot-jolt_linux-x86.so │ └── godot-jolt_linux-x86_editor.so │ ├── macos │ ├── godot-jolt_macos.framework │ │ ├── Resources │ │ │ └── Info.plist │ │ ├── _CodeSignature │ │ │ └── CodeResources │ │ └── godot-jolt_macos │ └── godot-jolt_macos_editor.framework │ │ ├── Resources │ │ └── Info.plist │ │ ├── _CodeSignature │ │ └── CodeResources │ │ └── godot-jolt_macos_editor │ └── windows │ ├── godot-jolt_windows-x64.dll │ ├── godot-jolt_windows-x64_editor.dll │ ├── godot-jolt_windows-x86.dll │ └── godot-jolt_windows-x86_editor.dll ├── default_env.tres ├── icon.png ├── icon.png.import ├── move.gd └── project.godot /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot-specific ignores 2 | .import/ 3 | export.cfg 4 | export_presets.cfg 5 | *.tmp 6 | 7 | # Imported translations (automatically generated from CSV files) 8 | *.translation 9 | 10 | # Mono-specific ignores 11 | .mono/ 12 | data_*/ 13 | # Godot 4+ specific ignores 14 | .godot/ 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 FreeFly 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Physics/player.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="PhysicsMaterial" load_steps=2 format=3 uid="uid://u55tuef0hp46"] 2 | 3 | [sub_resource type="GDScript" id="1"] 4 | 5 | [resource] 6 | script = SubResource("1") 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Code of interest in [move.gd](https://github.com/FreeFlyFall/RigidBodyController/blob/master/move.gd) 2 | 3 | # RigidBodyController 4 | The beginnings of a first person rigidbody character controller in Godot. Some of the benefits: 5 | - Pushing, being pushed by, and riding other objects with no extra code 6 | - Shotgun jumping and air controls 7 | - Movement acceleration and velocity limits 8 | - Velocity limits only apply to movement input. Outside forces, such as pushes or shotgun jumping can force the player above the velocity limit. 9 | The player can oppose these forces and slow down or move sideways, but can't add to the speed in the direction which is over the velocity limit. 10 | - Smooth movement transitions - inherent friction and inertia 11 | - Easy walking on slopes 12 | 13 | [Reddit Video](https://www.reddit.com/r/godot/comments/grxg1e/physics_based_character_controller/) 14 | -------------------------------------------------------------------------------- /Scenes/cuberb.gd: -------------------------------------------------------------------------------- 1 | extends RigidBody3D 2 | 3 | # Called when the node enters the scene tree for the first time. 4 | func _ready(): 5 | pass # Replace with function body. 6 | 7 | var once = false 8 | func _integrate_forces(state): 9 | if (once == false): 10 | once = true 11 | var direction = Vector3(0,0,1) 12 | #if state.get_linear_velocity().z < 5: 13 | state.apply_central_impulse(-direction*3000) 14 | -------------------------------------------------------------------------------- /Scenes/scene1.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=17 format=3 uid="uid://cwn6jw887nywo"] 2 | 3 | [ext_resource type="Script" path="res://move.gd" id="1"] 4 | [ext_resource type="PhysicsMaterial" uid="uid://u55tuef0hp46" path="res://Physics/player.tres" id="2"] 5 | [ext_resource type="Texture2D" uid="uid://c0lwdk68m5mt2" path="res://Textures/TexturesCom_Pavement_CobblestoneMossy01_2x2_1K_albedo.png" id="3_bxssy"] 6 | [ext_resource type="Texture2D" uid="uid://bjix76sl4cdwa" path="res://Textures/TexturesCom_RoughWoodPlanks_2x2_1K_albedo.png" id="6"] 7 | 8 | [sub_resource type="CapsuleShape3D" id="1"] 9 | 10 | [sub_resource type="CapsuleMesh" id="2"] 11 | 12 | [sub_resource type="VoxelGIData" id="20"] 13 | dynamic_range = 4.0 14 | propagation = 0.7 15 | 16 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_pc00p"] 17 | albedo_texture = ExtResource("6") 18 | uv1_scale = Vector3(2.595, 1.27, 0.67) 19 | 20 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_n2yvt"] 21 | albedo_texture = ExtResource("3_bxssy") 22 | uv1_triplanar = true 23 | uv1_world_triplanar = true 24 | 25 | [sub_resource type="BoxMesh" id="BoxMesh_hwgry"] 26 | material = SubResource("StandardMaterial3D_n2yvt") 27 | 28 | [sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_o3rtm"] 29 | data = PackedVector3Array(-0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5) 30 | 31 | [sub_resource type="PhysicsMaterial" id="PhysicsMaterial_en2a0"] 32 | friction = 0.0 33 | 34 | [sub_resource type="BoxMesh" id="BoxMesh_01c47"] 35 | 36 | [sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_ay55d"] 37 | points = PackedVector3Array(0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5) 38 | 39 | [sub_resource type="CapsuleMesh" id="CapsuleMesh_8wokw"] 40 | 41 | [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_wk1cy"] 42 | 43 | [node name="Node3D" type="Node3D"] 44 | 45 | [node name="Player" type="RigidBody3D" parent="."] 46 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.158582, 1.78085, 1.62877) 47 | axis_lock_angular_x = true 48 | axis_lock_angular_z = true 49 | mass = 0.939597 50 | physics_material_override = ExtResource("2") 51 | can_sleep = false 52 | continuous_cd = true 53 | contact_monitor = true 54 | max_contacts_reported = 5 55 | linear_damp = 0.01 56 | angular_damp = 10.0 57 | script = ExtResource("1") 58 | debug_lines = true 59 | accel = 100 60 | jump = 10 61 | air_control = 5 62 | turning_scale = 45.0 63 | walkable_normal = 0.5 64 | speed_to_crouch = 8 65 | friction_divider = 4 66 | 67 | [node name="CollisionShape3D" type="CollisionShape3D" parent="Player"] 68 | transform = Transform3D(1, -4.93969e-11, 1.16415e-10, 9.09495e-12, 1, -1.16415e-10, 0, 3.49246e-10, 1, 0, 0, 0) 69 | shape = SubResource("1") 70 | 71 | [node name="MeshInstance3D" type="MeshInstance3D" parent="Player"] 72 | transform = Transform3D(1, -1.07605e-10, 1.16415e-10, -4.87717e-11, 1, -3.49246e-10, 0, 1.04774e-09, 1, 0, 0, 0) 73 | layers = 2 74 | cast_shadow = 0 75 | mesh = SubResource("2") 76 | 77 | [node name="Head" type="Node3D" parent="."] 78 | transform = Transform3D(1, -0.000456549, 0.00051408, 0.000455753, 0.999999, 0.00154718, -0.000514786, -0.00154695, 0.999999, -7.25033, 3.80638, 5.18283) 79 | 80 | [node name="Pitch" type="Node3D" parent="Head"] 81 | 82 | [node name="Camera3D" type="Camera3D" parent="Head/Pitch"] 83 | transform = Transform3D(1, 1.82695e-10, 2.32831e-10, -8.13998e-11, 1, 4.88944e-09, 1.74623e-10, 0, 1, 0, 0, 0) 84 | cull_mask = 1048573 85 | fov = 101.1 86 | far = 500.0 87 | 88 | [node name="Camera3D2" type="Camera3D" parent="Head/Pitch/Camera3D"] 89 | transform = Transform3D(1, -1.66096e-10, 1.16415e-10, 1.83263e-10, 1, 0, -5.82077e-11, 0, 1, 7.05381, -2.53933, -1.41326) 90 | cull_mask = 1048573 91 | 92 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] 93 | transform = Transform3D(0.251867, 0.967762, 8.93903e-09, 0.0660924, -0.017201, 0.997665, 0.965503, -0.251279, -0.068294, 0.0889626, 16.6875, -0.00400639) 94 | light_color = Color(1, 0.988235, 0.878431, 1) 95 | light_energy = 3.923 96 | light_indirect_energy = 1.813 97 | light_volumetric_fog_energy = 0.36 98 | shadow_enabled = true 99 | 100 | [node name="VoxelGI" type="VoxelGI" parent="."] 101 | transform = Transform3D(1, 0, -8.74228e-08, 0, -1, 0, 8.74228e-08, 0, 1, 12.6872, 0.932631, -19.8859) 102 | size = Vector3(458.879, 50.0623, 207.626) 103 | data = SubResource("20") 104 | 105 | [node name="CSGBox3D2" type="CSGBox3D" parent="."] 106 | transform = Transform3D(20, 0, 0, 0, 0.0861957, 10.1396, 0, -0.0506982, 17.2391, 0, 1.70045, 16.5526) 107 | material_override = SubResource("StandardMaterial3D_pc00p") 108 | use_collision = true 109 | 110 | [node name="CSGBox3D3" type="CSGBox3D" parent="."] 111 | transform = Transform3D(-8.67993e-07, 0.0866026, -9.99998, 0.161603, 0.0499983, 17.3199, 19.9993, -0.000404004, -0.139953, -16.8382, 1.51522, 21.4435) 112 | material_override = SubResource("StandardMaterial3D_pc00p") 113 | use_collision = true 114 | 115 | [node name="CSGBox3D6" type="CSGBox3D" parent="."] 116 | transform = Transform3D(-8.64267e-07, 0.1, -3.92087e-06, 0.161603, -8.71491e-08, 19.9993, 19.9993, 5.18048e-09, -0.161603, -15.6913, 1.82469, 31.9274) 117 | material_override = SubResource("StandardMaterial3D_pc00p") 118 | use_collision = true 119 | 120 | [node name="CSGBox3D4" type="CSGBox3D" parent="."] 121 | transform = Transform3D(-8.64267e-07, 0.0707108, -14.1421, 0.161603, 0.0707083, 14.1416, 19.9993, -0.000571351, -0.114271, -16.4489, 1.57503, 1.03087) 122 | material_override = SubResource("StandardMaterial3D_pc00p") 123 | use_collision = true 124 | 125 | [node name="CSGBox3D5" type="CSGBox3D" parent="."] 126 | transform = Transform3D(-8.56817e-07, 0.0965926, -5.17637, 0.161603, 0.025881, 19.3178, 19.9993, -0.000209125, -0.156097, -16.4489, 1.79964, 28.8271) 127 | material_override = SubResource("StandardMaterial3D_pc00p") 128 | use_collision = true 129 | 130 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 131 | transform = Transform3D(265.35, -0.000913893, 0.409863, 0.241657, 0.999995, 1.23447, -0.273384, -0.00309366, 398.909, -0.639654, -0.0624347, -3.05023) 132 | mesh = SubResource("BoxMesh_hwgry") 133 | skeleton = NodePath("") 134 | 135 | [node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"] 136 | 137 | [node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"] 138 | shape = SubResource("ConcavePolygonShape3D_o3rtm") 139 | 140 | [node name="RigidBody3D3" type="RigidBody3D" parent="."] 141 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.96149, 1.59805, 10.04) 142 | mass = 1.119 143 | physics_material_override = SubResource("PhysicsMaterial_en2a0") 144 | 145 | [node name="MeshInstance3D" type="MeshInstance3D" parent="RigidBody3D3"] 146 | transform = Transform3D(4.89632, 0, 0, 0, 0.420798, 0, 0, 0, 6.16068, 0, 0, 0) 147 | mesh = SubResource("BoxMesh_01c47") 148 | 149 | [node name="CollisionShape3D" type="CollisionShape3D" parent="RigidBody3D3"] 150 | transform = Transform3D(4.89632, 0, 0, 0, 0.420798, 0, 0, 0, 6.16068, 0, 0, 0) 151 | shape = SubResource("ConvexPolygonShape3D_ay55d") 152 | 153 | [node name="StaticBodyRect" type="StaticBody3D" parent="."] 154 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.27041, 0.692766, 3.0415) 155 | physics_material_override = SubResource("PhysicsMaterial_en2a0") 156 | 157 | [node name="MeshInstance3D" type="MeshInstance3D" parent="StaticBodyRect"] 158 | transform = Transform3D(4.89632, 0, 0, 0, 0.189687, 0, 0, 0, 6.16068, 0, 0, 0) 159 | mesh = SubResource("BoxMesh_01c47") 160 | 161 | [node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBodyRect"] 162 | transform = Transform3D(4.89632, 0, 0, 0, 0.189687, 0, 0, 0, 6.16068, 0, 0, 0) 163 | shape = SubResource("ConvexPolygonShape3D_ay55d") 164 | 165 | [node name="RigidBody3D" type="RigidBody3D" parent="."] 166 | transform = Transform3D(1, -0.000456549, 0.00051408, 0.000455753, 0.999999, 0.00154718, -0.000514786, -0.00154695, 0.999999, -0.32015, 1.47502, -0.495072) 167 | 168 | [node name="MeshInstance3D" type="MeshInstance3D" parent="RigidBody3D"] 169 | mesh = SubResource("CapsuleMesh_8wokw") 170 | 171 | [node name="CollisionShape3D" type="CollisionShape3D" parent="RigidBody3D"] 172 | shape = SubResource("CapsuleShape3D_wk1cy") 173 | -------------------------------------------------------------------------------- /Scripts/Draw3D.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | func line(start: Vector3, end: Vector3, color = Color.MAGENTA, persist_seconds: float = 0): 4 | var mesh_instance := MeshInstance3D.new() 5 | var immediate_mesh := ImmediateMesh.new() 6 | var material := ORMMaterial3D.new() 7 | 8 | mesh_instance.mesh = immediate_mesh 9 | mesh_instance.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF 10 | 11 | immediate_mesh.surface_begin(Mesh.PRIMITIVE_LINES, material) 12 | immediate_mesh.surface_add_vertex(start) 13 | immediate_mesh.surface_add_vertex(end) 14 | immediate_mesh.surface_end() 15 | 16 | material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED 17 | material.albedo_color = color 18 | 19 | get_tree().get_root().add_child(mesh_instance) 20 | 21 | if persist_seconds: 22 | await get_tree().create_timer(persist_seconds).timeout 23 | mesh_instance.queue_free() 24 | else: 25 | return mesh_instance 26 | -------------------------------------------------------------------------------- /Scripts/DrawLine3D.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | func line(pos1: Vector3, pos2: Vector3, color = Color.WHITE_SMOKE, persist_seconds = 0): 4 | var mesh_instance := MeshInstance3D.new() 5 | var immediate_mesh := ImmediateMesh.new() 6 | var material := ORMMaterial3D.new() 7 | 8 | mesh_instance.mesh = immediate_mesh 9 | mesh_instance.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF 10 | 11 | immediate_mesh.surface_begin(Mesh.PRIMITIVE_LINES, material) 12 | immediate_mesh.surface_add_vertex(pos1) 13 | immediate_mesh.surface_add_vertex(pos2) 14 | immediate_mesh.surface_end() 15 | 16 | material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED 17 | material.albedo_color = color 18 | 19 | return await final_cleanup(mesh_instance, persist_seconds) 20 | 21 | func point(pos: Vector3, radius = 0.05, color = Color.WHITE_SMOKE, persist_seconds = 0): 22 | var mesh_instance := MeshInstance3D.new() 23 | var sphere_mesh := SphereMesh.new() 24 | var material := ORMMaterial3D.new() 25 | 26 | mesh_instance.mesh = sphere_mesh 27 | mesh_instance.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF 28 | mesh_instance.position = pos 29 | 30 | sphere_mesh.radius = radius 31 | sphere_mesh.height = radius*2 32 | sphere_mesh.material = material 33 | 34 | material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED 35 | material.albedo_color = color 36 | 37 | return await final_cleanup(mesh_instance, persist_seconds) 38 | 39 | func final_cleanup(mesh_instance: MeshInstance3D, persist_seconds: float): 40 | get_tree().get_root().add_child(mesh_instance) 41 | if persist_seconds == 0: 42 | await get_tree().physics_frame 43 | mesh_instance.queue_free() 44 | elif persist_seconds > 0: 45 | await get_tree().create_timer(persist_seconds).timeout 46 | mesh_instance.queue_free() 47 | else: 48 | return mesh_instance 49 | -------------------------------------------------------------------------------- /Scripts/draw.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Node3D 3 | 4 | # Test tool to draw lines 5 | # Note: Drawing at translation draws at top of capsule, not player origin 6 | 7 | var raycast_list = Array() 8 | var start = 1.2 9 | var bottom = 0.26 10 | # Cardinal vector distance 11 | var cv_dist = 0.5 12 | # Secondary vector distance 13 | # Added to 2 cardinal vectors to result in a diagonal with the same maginitude of a cardinal vector 14 | var sv_dist= cv_dist/sqrt(2) 15 | 16 | # Called when the node enters the scene tree for the first time. 17 | func _ready(): 18 | pass # Replace with function body. 19 | 20 | func _process(_delta): 21 | raycast_list.clear() 22 | 23 | for i in 8: 24 | var loc = get_node('Player').position 25 | loc.y -= start 26 | match i: 27 | # Cardinal vectors 28 | 0: 29 | loc.z -= cv_dist 30 | 1: 31 | loc.z += cv_dist 32 | 2: 33 | loc.x += cv_dist 34 | 3: 35 | loc.x -= cv_dist 36 | # Secondary vectors 37 | 4: 38 | loc.z -= sv_dist 39 | loc.x += sv_dist 40 | 5: 41 | loc.z += sv_dist 42 | loc.x += sv_dist 43 | 6: 44 | loc.z -= sv_dist 45 | loc.x -= sv_dist 46 | 7: 47 | loc.z += sv_dist 48 | loc.x -= sv_dist 49 | var loc2 = loc 50 | loc2.y -= bottom 51 | raycast_list.append([loc,loc2]) 52 | var draw = get_node("draw") 53 | draw.clear() 54 | for array in raycast_list: 55 | draw.begin(Mesh.PRIMITIVE_LINE_STRIP) 56 | draw.add_vertex(array[0]) 57 | draw.add_vertex(array[1]) 58 | draw.end() 59 | -------------------------------------------------------------------------------- /Textures/TexturesCom_Pavement_CobblestoneMossy01_2x2_1K_albedo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/Textures/TexturesCom_Pavement_CobblestoneMossy01_2x2_1K_albedo.png -------------------------------------------------------------------------------- /Textures/TexturesCom_Pavement_CobblestoneMossy01_2x2_1K_albedo.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://c0lwdk68m5mt2" 6 | path.s3tc="res://.godot/imported/TexturesCom_Pavement_CobblestoneMossy01_2x2_1K_albedo.png-9f3810e8e6b4572cdcd221b5dd6cbf0c.s3tc.ctex" 7 | metadata={ 8 | "imported_formats": ["s3tc_bptc"], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://Textures/TexturesCom_Pavement_CobblestoneMossy01_2x2_1K_albedo.png" 15 | dest_files=["res://.godot/imported/TexturesCom_Pavement_CobblestoneMossy01_2x2_1K_albedo.png-9f3810e8e6b4572cdcd221b5dd6cbf0c.s3tc.ctex"] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/high_quality=false 21 | compress/lossy_quality=0.7 22 | compress/hdr_compression=1 23 | compress/normal_map=0 24 | compress/channel_pack=0 25 | mipmaps/generate=true 26 | mipmaps/limit=-1 27 | roughness/mode=0 28 | roughness/src_normal="" 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/normal_map_invert_y=false 32 | process/hdr_as_srgb=false 33 | process/hdr_clamp_exposure=false 34 | process/size_limit=0 35 | detect_3d/compress_to=0 36 | -------------------------------------------------------------------------------- /Textures/TexturesCom_RoughWoodPlanks_2x2_1K_albedo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/Textures/TexturesCom_RoughWoodPlanks_2x2_1K_albedo.png -------------------------------------------------------------------------------- /Textures/TexturesCom_RoughWoodPlanks_2x2_1K_albedo.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bjix76sl4cdwa" 6 | path.s3tc="res://.godot/imported/TexturesCom_RoughWoodPlanks_2x2_1K_albedo.png-2f8d888284d62b34a8ec4351f5015aa8.s3tc.ctex" 7 | metadata={ 8 | "imported_formats": ["s3tc_bptc"], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://Textures/TexturesCom_RoughWoodPlanks_2x2_1K_albedo.png" 15 | dest_files=["res://.godot/imported/TexturesCom_RoughWoodPlanks_2x2_1K_albedo.png-2f8d888284d62b34a8ec4351f5015aa8.s3tc.ctex"] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/high_quality=false 21 | compress/lossy_quality=0.7 22 | compress/hdr_compression=1 23 | compress/normal_map=0 24 | compress/channel_pack=0 25 | mipmaps/generate=true 26 | mipmaps/limit=-1 27 | roughness/mode=0 28 | roughness/src_normal="" 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/normal_map_invert_y=false 32 | process/hdr_as_srgb=false 33 | process/hdr_clamp_exposure=false 34 | process/size_limit=0 35 | detect_3d/compress_to=0 36 | -------------------------------------------------------------------------------- /addons/godot-jolt/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Mikael Hermansson and Godot Jolt contributors. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /addons/godot-jolt/THIRDPARTY.txt: -------------------------------------------------------------------------------- 1 | Godot Jolt incorporates third-party material from the projects listed below. 2 | 3 | Godot Engine (https://github.com/godotengine/godot) 4 | 5 | Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). 6 | Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to 10 | deal in the Software without restriction, including without limitation the 11 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | sell copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | IN THE SOFTWARE. 25 | 26 | godot-cpp (https://github.com/godot-jolt/godot-cpp) 27 | 28 | Copyright (c) 2017-present Godot Engine contributors. 29 | Copyright (c) 2022-present Mikael Hermansson. 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy 32 | of this software and associated documentation files (the "Software"), to 33 | deal in the Software without restriction, including without limitation the 34 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 35 | sell copies of the Software, and to permit persons to whom the Software is 36 | furnished to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in 39 | all copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 46 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 47 | IN THE SOFTWARE. 48 | 49 | Jolt Physics (https://github.com/godot-jolt/jolt) 50 | 51 | Copyright (c) 2021 Jorrit Rouwe. 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a copy 54 | of this software and associated documentation files (the "Software"), to 55 | deal in the Software without restriction, including without limitation the 56 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 57 | sell copies of the Software, and to permit persons to whom the Software is 58 | furnished to do so, subject to the following conditions: 59 | 60 | The above copyright notice and this permission notice shall be included in 61 | all copies or substantial portions of the Software. 62 | 63 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 66 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 67 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 68 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 69 | IN THE SOFTWARE. 70 | 71 | mimalloc (https://github.com/godot-jolt/mimalloc) 72 | 73 | Copyright (c) 2018-2021 Microsoft Corporation, Daan Leijen. 74 | 75 | Permission is hereby granted, free of charge, to any person obtaining a copy 76 | of this software and associated documentation files (the "Software"), to 77 | deal in the Software without restriction, including without limitation the 78 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 79 | sell copies of the Software, and to permit persons to whom the Software is 80 | furnished to do so, subject to the following conditions: 81 | 82 | The above copyright notice and this permission notice shall be included in 83 | all copies or substantial portions of the Software. 84 | 85 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 86 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 87 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 88 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 89 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 90 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 91 | IN THE SOFTWARE. 92 | -------------------------------------------------------------------------------- /addons/godot-jolt/godot-jolt.gdextension: -------------------------------------------------------------------------------- 1 | [configuration] 2 | 3 | entry_symbol = "godot_jolt_main" 4 | compatibility_minimum = "4.1" 5 | 6 | [libraries] 7 | 8 | windows.release.x86_64 = "windows/godot-jolt_windows-x64.dll" 9 | windows.debug.x86_64 = "windows/godot-jolt_windows-x64_editor.dll" 10 | 11 | windows.release.x86_32 = "windows/godot-jolt_windows-x86.dll" 12 | windows.debug.x86_32 = "windows/godot-jolt_windows-x86_editor.dll" 13 | 14 | linux.release.x86_64 = "linux/godot-jolt_linux-x64.so" 15 | linux.debug.x86_64 = "linux/godot-jolt_linux-x64_editor.so" 16 | 17 | linux.release.x86_32 = "linux/godot-jolt_linux-x86.so" 18 | linux.debug.x86_32 = "linux/godot-jolt_linux-x86_editor.so" 19 | 20 | macos.release = "macos/godot-jolt_macos.framework" 21 | macos.debug = "macos/godot-jolt_macos_editor.framework" 22 | -------------------------------------------------------------------------------- /addons/godot-jolt/linux/godot-jolt_linux-x64.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/linux/godot-jolt_linux-x64.so -------------------------------------------------------------------------------- /addons/godot-jolt/linux/godot-jolt_linux-x64_editor.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/linux/godot-jolt_linux-x64_editor.so -------------------------------------------------------------------------------- /addons/godot-jolt/linux/godot-jolt_linux-x86.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/linux/godot-jolt_linux-x86.so -------------------------------------------------------------------------------- /addons/godot-jolt/linux/godot-jolt_linux-x86_editor.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/linux/godot-jolt_linux-x86_editor.so -------------------------------------------------------------------------------- /addons/godot-jolt/macos/godot-jolt_macos.framework/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleInfoDictionaryVersion 6 | 6.0 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | godot-jolt_macos 11 | CFBundleName 12 | Godot Jolt 13 | CFBundleDisplayName 14 | Godot Jolt 15 | CFBundleIdentifier 16 | org.godot-jolt.godot-jolt 17 | NSHumanReadableCopyright 18 | Copyright (c) Mikael Hermansson and Godot Jolt contributors. 19 | CFBundleVersion 20 | 0.9.0 21 | CFBundleShortVersionString 22 | 0.9.0 23 | CFBundlePackageType 24 | FMWK 25 | CSResourcesFileMapped 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /addons/godot-jolt/macos/godot-jolt_macos.framework/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Resources/Info.plist 8 | 9 | YuYYY8jBb0arCbHUJAYnYXN9Bl4= 10 | 11 | 12 | files2 13 | 14 | Resources/Info.plist 15 | 16 | hash2 17 | 18 | mUhdhGCxAeqGTDJQas4Ic9bzBCzZ6+vQ9lFDcNV630o= 19 | 20 | 21 | 22 | rules 23 | 24 | ^Resources/ 25 | 26 | ^Resources/.*\.lproj/ 27 | 28 | optional 29 | 30 | weight 31 | 1000 32 | 33 | ^Resources/.*\.lproj/locversion.plist$ 34 | 35 | omit 36 | 37 | weight 38 | 1100 39 | 40 | ^Resources/Base\.lproj/ 41 | 42 | weight 43 | 1010 44 | 45 | ^version.plist$ 46 | 47 | 48 | rules2 49 | 50 | .*\.dSYM($|/) 51 | 52 | weight 53 | 11 54 | 55 | ^(.*/)?\.DS_Store$ 56 | 57 | omit 58 | 59 | weight 60 | 2000 61 | 62 | ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ 63 | 64 | nested 65 | 66 | weight 67 | 10 68 | 69 | ^.* 70 | 71 | ^Info\.plist$ 72 | 73 | omit 74 | 75 | weight 76 | 20 77 | 78 | ^PkgInfo$ 79 | 80 | omit 81 | 82 | weight 83 | 20 84 | 85 | ^Resources/ 86 | 87 | weight 88 | 20 89 | 90 | ^Resources/.*\.lproj/ 91 | 92 | optional 93 | 94 | weight 95 | 1000 96 | 97 | ^Resources/.*\.lproj/locversion.plist$ 98 | 99 | omit 100 | 101 | weight 102 | 1100 103 | 104 | ^Resources/Base\.lproj/ 105 | 106 | weight 107 | 1010 108 | 109 | ^[^/]+$ 110 | 111 | nested 112 | 113 | weight 114 | 10 115 | 116 | ^embedded\.provisionprofile$ 117 | 118 | weight 119 | 20 120 | 121 | ^version\.plist$ 122 | 123 | weight 124 | 20 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /addons/godot-jolt/macos/godot-jolt_macos.framework/godot-jolt_macos: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/macos/godot-jolt_macos.framework/godot-jolt_macos -------------------------------------------------------------------------------- /addons/godot-jolt/macos/godot-jolt_macos_editor.framework/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleInfoDictionaryVersion 6 | 6.0 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | godot-jolt_macos_editor 11 | CFBundleName 12 | Godot Jolt 13 | CFBundleDisplayName 14 | Godot Jolt 15 | CFBundleIdentifier 16 | org.godot-jolt.godot-jolt 17 | NSHumanReadableCopyright 18 | Copyright (c) Mikael Hermansson and Godot Jolt contributors. 19 | CFBundleVersion 20 | 0.9.0 21 | CFBundleShortVersionString 22 | 0.9.0 23 | CFBundlePackageType 24 | FMWK 25 | CSResourcesFileMapped 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /addons/godot-jolt/macos/godot-jolt_macos_editor.framework/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Resources/Info.plist 8 | 9 | g2kDFUAKlkXWSjx4ILQBttcmXe8= 10 | 11 | 12 | files2 13 | 14 | Resources/Info.plist 15 | 16 | hash2 17 | 18 | 8VcK9urwJzy+lEmTjkhZhwvnKsewbfJyRy25JLd26h0= 19 | 20 | 21 | 22 | rules 23 | 24 | ^Resources/ 25 | 26 | ^Resources/.*\.lproj/ 27 | 28 | optional 29 | 30 | weight 31 | 1000 32 | 33 | ^Resources/.*\.lproj/locversion.plist$ 34 | 35 | omit 36 | 37 | weight 38 | 1100 39 | 40 | ^Resources/Base\.lproj/ 41 | 42 | weight 43 | 1010 44 | 45 | ^version.plist$ 46 | 47 | 48 | rules2 49 | 50 | .*\.dSYM($|/) 51 | 52 | weight 53 | 11 54 | 55 | ^(.*/)?\.DS_Store$ 56 | 57 | omit 58 | 59 | weight 60 | 2000 61 | 62 | ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ 63 | 64 | nested 65 | 66 | weight 67 | 10 68 | 69 | ^.* 70 | 71 | ^Info\.plist$ 72 | 73 | omit 74 | 75 | weight 76 | 20 77 | 78 | ^PkgInfo$ 79 | 80 | omit 81 | 82 | weight 83 | 20 84 | 85 | ^Resources/ 86 | 87 | weight 88 | 20 89 | 90 | ^Resources/.*\.lproj/ 91 | 92 | optional 93 | 94 | weight 95 | 1000 96 | 97 | ^Resources/.*\.lproj/locversion.plist$ 98 | 99 | omit 100 | 101 | weight 102 | 1100 103 | 104 | ^Resources/Base\.lproj/ 105 | 106 | weight 107 | 1010 108 | 109 | ^[^/]+$ 110 | 111 | nested 112 | 113 | weight 114 | 10 115 | 116 | ^embedded\.provisionprofile$ 117 | 118 | weight 119 | 20 120 | 121 | ^version\.plist$ 122 | 123 | weight 124 | 20 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /addons/godot-jolt/macos/godot-jolt_macos_editor.framework/godot-jolt_macos_editor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/macos/godot-jolt_macos_editor.framework/godot-jolt_macos_editor -------------------------------------------------------------------------------- /addons/godot-jolt/windows/godot-jolt_windows-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/windows/godot-jolt_windows-x64.dll -------------------------------------------------------------------------------- /addons/godot-jolt/windows/godot-jolt_windows-x64_editor.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/windows/godot-jolt_windows-x64_editor.dll -------------------------------------------------------------------------------- /addons/godot-jolt/windows/godot-jolt_windows-x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/windows/godot-jolt_windows-x86.dll -------------------------------------------------------------------------------- /addons/godot-jolt/windows/godot-jolt_windows-x86_editor.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/addons/godot-jolt/windows/godot-jolt_windows-x86_editor.dll -------------------------------------------------------------------------------- /default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=3 uid="uid://b7euq6q2t2jiy"] 2 | 3 | [sub_resource type="Sky" id="1"] 4 | 5 | [resource] 6 | background_mode = 2 7 | sky = SubResource("1") 8 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeFlyFall/RigidBodyController/53ac733a40e90fe00ef3ade050dea703e2c96f2c/icon.png -------------------------------------------------------------------------------- /icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bx7v0us21yvnr" 6 | path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.png" 14 | dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /move.gd: -------------------------------------------------------------------------------- 1 | extends RigidBody3D 2 | 3 | ### Use the Jolt physics engine 4 | 5 | #DevNotes to-do: 6 | # Separate concerns for mouse and movement input handling, collider and mesh resizing 7 | # Add dash with set velocity? 8 | # Newton's third law eventually breaks. Wondering whether it's a physics engine bug. 9 | 10 | ### Global 11 | 12 | ## Whether to draw the debug lines for forces 13 | @export var debug_lines: bool 14 | ## Whether to print normals at the points of contact with the player capsule 15 | @export var debug_contact_normals: bool 16 | ## Whether to print details for groundedness checks 17 | @export var debug_groundedness: bool 18 | var is_grounded: bool # Whether the player is considered to be touching a walkable slope 19 | @onready var capsule = $CollisionShape3D.shape # Capsule collision shape of the player 20 | @onready var capsule_mesh = $MeshInstance3D.mesh # Capsule mesh shape 21 | @onready var camera = $"../Head/Pitch/Camera3D" # Camera3D node 22 | @onready var head = $"../Head" # y-axis rotation node (look left and right) 23 | 24 | ### Input vars 25 | @onready var pitch = $"../Head/Pitch" # x-axis rotation node (look up and down) 26 | 27 | ### Integrate forces vars 28 | 29 | ## Player acceleration force. 30 | @export var accel: int 31 | ## Jump force multiplier. 32 | @export var jump: int 33 | ## Air control multiplier. 34 | @export var air_control: int 35 | ## How quickly to scale movement toward a turning direction. Lower is more. 36 | @export_range(15, 120, 1) var turning_scale: float 37 | ## Mouse sensetivity. Default: 0.05. 38 | @export var mouse_sensitivity: float = 0.05 39 | ## Defines the steepest walkable slope. Lower is steeper. Default: 0.5. 40 | @export_range(0, 1, 0.01) var walkable_normal: float 41 | ## The rate at which the player moves in or out of the crouching position. High values may cause physics glitches. 42 | @export_range(2, 20) var speed_to_crouch: int 43 | ## Default speed limit of the player. Default: 8. 44 | @export var speed_limit: float = 8 45 | ## Speed to move at while crouching. Default: 4. 46 | @export var crouching_speed_limit: float = 4 47 | ## Speed to move at while sprinting. Default: 12. 48 | @export var sprinting_speed_limit: float = 12 49 | ## Amount to divide the friction by when not grounded (prevents sticking to walls that may come from air control). Default: 3. 50 | @export var friction_divider = 3 51 | var steepest_slope_normal: Vector3 # Stores the lowest (steepest) normal of the contact with the player collider 52 | var shallowest_slope_normal: Vector3 # Stores the highest (flattest) normal of the contact with the player collider 53 | var slope_normal: Vector3 # Stores normals of contact points for iteration 54 | var contacted_body: RigidBody3D # Rigid body the player is currently contacting, if there is one 55 | var player_physics_material = load("res://Physics/player.tres") 56 | var local_friction = player_physics_material.friction # Editor friction value 57 | var is_landing: bool = true # Whether the player has jumped and let go of jump 58 | var is_jumping: bool = false # Whether the player has jumped 59 | ## Stores preference for the delta time before the player can jump again. Default: 0.1. 60 | @export_range(0.01,1,0.01) var JUMP_THROTTLE: float = 0.1 61 | var jump_throttle: float # Variable used with jump throttling calculations 62 | ## Downward force multiplier to apply when letting go of space while jumping, in order to assist with landing. Default: 1.5. 63 | @export var landing_assist: float = 1.5 64 | ## Amount of force to stop sliding with (alternative to friction). Default: 3. 65 | @export_range(0.1,100,0.1) var anti_slide_force: float = 3 66 | ## Number of hitscans to use around the base of the player capsule to detect groundedness. 67 | @export var groundedness_hitscan_count: int = 12 68 | 69 | ### Physics process vars 70 | var original_height: float 71 | var crouching_height: float 72 | var current_speed_limit: float # Current speed limit to use. For standing or crouching. 73 | var posture # Current posture state 74 | enum { WALKING, CROUCHING, SPRINTING } # Possible values for posture 75 | 76 | ### Misc 77 | var ld = preload("res://Scripts//DrawLine3D.gd").new() 78 | 79 | func draw_arrow(pos1: Vector3, pos2: Vector3, color = Color.WHITE_SMOKE, persist_seconds = 0): 80 | ld.line(pos1, pos2, color, persist_seconds) 81 | ld.point(pos1, 0.0075, color, persist_seconds) 82 | 83 | ### Godot notification functions ### 84 | func _ready(): 85 | # Get capsule variables 86 | original_height = capsule.height 87 | crouching_height = capsule.height / 2 88 | Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) # Capture and hide mouse 89 | add_child(ld) # Add line drawer 90 | 91 | 92 | func _input(event): 93 | # Player look 94 | if event is InputEventMouseMotion: 95 | head.rotate_y(deg_to_rad(-event.relative.x * mouse_sensitivity)) 96 | pitch.rotate_x(deg_to_rad(-event.relative.y * mouse_sensitivity)) 97 | pitch.rotation.x = clamp(pitch.rotation.x, deg_to_rad(-90), deg_to_rad(90)) 98 | # Capture and release mouse 99 | if event.is_action_pressed("ui_cancel"): 100 | if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: 101 | Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) # Free the mouse 102 | else: 103 | Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) 104 | 105 | 106 | var is_done_shrinking: bool # temporary # Whether the player is currently shrinking towards being crouched 107 | func _physics_process(delta): 108 | # Keep camera with player 109 | head.position = self.position + Vector3.UP * capsule.height / 2 110 | 111 | ### Player posture FSM 112 | if Input.is_action_pressed("crouch"): 113 | posture = CROUCHING 114 | elif Input.is_action_pressed("sprint"): 115 | posture = SPRINTING 116 | else: 117 | posture = WALKING 118 | 119 | ### Groundedness raycasts 120 | is_grounded = false 121 | # Define raycast info used with detecting groundedness 122 | var raycast_list = Array() # List of raycasts used with detecting groundedness 123 | var bottom = Vector3(0, 0.2, 0) # Distance down from start to fire the raycast to 124 | var start = (capsule.height / 2) - 0.2 # Start point down from the center of the player to start the raycast 125 | var edge_vector = Vector3(0, 0, capsule.radius - 0.1) # Initial vector toward the edge of the capsule 126 | # Get world state for collisions 127 | var direct_state = get_world_3d().direct_space_state 128 | raycast_list.clear() 129 | 130 | ## Create raycasts around the player capsule. They begin towards the edge of the radius, and shoot from just 131 | ## below the capsule to just below the bottom bounds of the capsule, with one raycast down from the center. 132 | # Get the starting location for the hitscans 133 | var location: Vector3 = self.position 134 | location.y -= start 135 | # Create the center raycast 136 | raycast_list.append([location, location - bottom]) 137 | # Create the raycasts out from the center of the capsule 138 | for i in groundedness_hitscan_count: 139 | var working_location = location 140 | # The vector is rotated around the y-axis before applying to the edge vector to the centered point 141 | working_location += edge_vector.rotated(Vector3(0, 1, 0), deg_to_rad((i + 1) * 360.0 / groundedness_hitscan_count)) 142 | # Subtract from the working location's vertical axis to get the ending point 143 | var end_point = working_location - bottom 144 | # Add an array, containing the two points for this iteration, to the list of raycasts 145 | raycast_list.append([working_location, end_point]) 146 | # Check each raycast for collision, ignoring the capsule itself 147 | for array in raycast_list: 148 | var params = PhysicsRayQueryParameters3D.new() 149 | params.from = array[0] 150 | params.to = array[1] 151 | params.exclude = [self] 152 | if debug_lines: ld.line(array[0], array[1], Color.CHARTREUSE, 0) 153 | var collision = direct_state.intersect_ray(params) 154 | # The player is grounded if any of the raycasts hit 155 | if collision and is_walkable(collision.normal.y): 156 | is_grounded = true 157 | if debug_groundedness: print("Grounded Hitscans: "+str(is_grounded)) 158 | 159 | 160 | ### Sprinting & Crouching 161 | var capsule_scale = delta * speed_to_crouch # Amount to change capsule height up or down 162 | var move_camera = delta / 2 * speed_to_crouch # Amount to move camera while crouching 163 | match posture: 164 | SPRINTING: 165 | current_speed_limit = sprinting_speed_limit 166 | grow_capsule(is_done_shrinking, capsule_scale, move_camera) 167 | CROUCHING: # Shrink 168 | current_speed_limit = crouching_speed_limit 169 | if capsule.height > crouching_height: 170 | capsule.height -= capsule_scale 171 | capsule_mesh.height -= capsule_scale 172 | elif is_done_shrinking == false: 173 | ## Adding a force to work around some physics glitches for the moment 174 | #var look_direction = head.transform.basis.z 175 | #self.apply_central_force(look_direction * mass * 100) 176 | is_done_shrinking = true 177 | WALKING: # Grow 178 | current_speed_limit = speed_limit 179 | grow_capsule(is_done_shrinking, capsule_scale, move_camera) 180 | 181 | # Setup jump throttle for integrate_forces 182 | if is_jumping or is_landing: 183 | jump_throttle -= delta 184 | else: 185 | jump_throttle = JUMP_THROTTLE 186 | 187 | 188 | func _integrate_forces(state): 189 | steepest_slope_normal = Vector3(0, 1, 0) 190 | shallowest_slope_normal = Vector3(0, -1, 0) 191 | contacted_body = null # Rigidbody 192 | # Velocity of the Rigidbody the player is contacting 193 | var contacted_body_vel_at_point = Vector3() 194 | 195 | ### Grounding, slopes, & rigidbody contact point 196 | # If the player body is contacting something 197 | var shallowest_contact_index: int = -1 198 | 199 | if state.get_contact_count() > 0: 200 | # Iterate over the capsule contact points and get the steepest/shallowest slopes 201 | for i in state.get_contact_count(): 202 | slope_normal = state.get_contact_local_normal(i) 203 | if slope_normal.y < steepest_slope_normal.y: # Lower normal means steeper slope 204 | steepest_slope_normal = slope_normal 205 | if slope_normal.y > shallowest_slope_normal.y: 206 | shallowest_slope_normal = slope_normal 207 | shallowest_contact_index = i 208 | if debug_contact_normals: print("Steepest normal: "+str(steepest_slope_normal)) 209 | if debug_contact_normals: print("Shallowest normal: "+str(shallowest_slope_normal)) 210 | #### If the steepest slope contacted is more shallow than the walkable_normal, the player is grounded 211 | ####if is_walkable(steepest_slope_normal.y): 212 | ####is_grounded = true 213 | # If the shallowest slope normal is walkabe, the player is grounded #### Else if the shallowest slope normal is not walkable, the player is not grounded 214 | if is_walkable(shallowest_slope_normal.y): 215 | is_grounded = true 216 | if debug_groundedness: print("Grounded Contacts: "+str(is_grounded)) 217 | # If a rigidbody is contacted, get the velocity at contact to be used with relative velocity calculations 218 | if shallowest_contact_index >= 0: 219 | var contact_position = state.get_contact_collider_position(0) # coords of the contact point from center of contacted body 220 | var collisions = get_colliding_bodies() 221 | var rb_collision_idx = null # rigidbody collision index 222 | if collisions.size() > 0: 223 | for collision_idx in collisions.size(): 224 | if collisions[collision_idx].get_class() == "RigidBody3D": 225 | rb_collision_idx = collision_idx 226 | # Only use the relative velocity of the contacted body if it's considered walkable 227 | ## This prevents the relative velocity calculations from adding continual sideways force to an object 228 | if (rb_collision_idx != null and is_walkable(steepest_slope_normal.y)): 229 | contacted_body = collisions[rb_collision_idx] 230 | contacted_body_vel_at_point = state.get_contact_collider_velocity_at_position(rb_collision_idx) 231 | #contacted_body_vel_at_point = get_contacted_body_velocity_at_point( 232 | # contacted_body, contact_position 233 | #) 234 | 235 | ### Jumping: Should allow the player to jump, and hold jump to jump again if they become grounded after a throttling period 236 | var has_walkable_contact: bool = ( 237 | state.get_contact_count() > 0 and is_walkable(shallowest_slope_normal.y) 238 | ) # Different from is_grounded 239 | # If the player is trying to jump, the throttle expired, the player is grounded, and they're not already jumping, jump 240 | # Check for is_jumping is because contact still exists at the beginning of a jump for more than one physics frame 241 | if ( 242 | Input.is_action_pressed("jump") 243 | and jump_throttle < 0 244 | and has_walkable_contact 245 | and not is_jumping 246 | ): 247 | state.apply_central_impulse(Vector3(0, 1, 0) * jump) 248 | is_jumping = true 249 | is_landing = false 250 | # Apply a downward force once if the player lets go of jump to assist with landing 251 | if Input.is_action_just_released("jump"): 252 | if is_landing == false: # Only apply the landing assist force once 253 | is_landing = true 254 | if not has_walkable_contact: 255 | state.apply_central_impulse(Vector3(0, -1, 0) * landing_assist) 256 | # If the player becomes grounded, they're no longer considered to be jumping 257 | if has_walkable_contact: 258 | is_jumping = false 259 | 260 | ### Movement 261 | var move = relative_input() # Get movement vector relative to player orientation 262 | var move2 = Vector2(move.x, move.z) # Convert movement for Vector2 methods 263 | 264 | set_friction() 265 | 266 | # Get the player velocity, relative to the contacting body if there is one 267 | var vel = Vector3() 268 | if is_grounded: 269 | ## Keep vertical velocity if grounded. vel will be normalized below 270 | ## accounting for the y value, preventing faster movement on slopes. 271 | vel = state.get_linear_velocity() 272 | vel -= contacted_body_vel_at_point 273 | else: 274 | ## Remove y value of velocity so only horizontal speed is checked in the air. 275 | ## Without this, the normalized vel causes the speed limit check to 276 | ## progressively limit the player from moving horizontally in relation to vertical speed. 277 | vel = Vector3(state.get_linear_velocity().x, 0, state.get_linear_velocity().z) 278 | vel -= Vector3(contacted_body_vel_at_point.x, 0, contacted_body_vel_at_point.z) 279 | # Get a normalized player velocity 280 | var nvel = vel.normalized() 281 | var nvel2 = Vector2(nvel.x, nvel.z) # 2D velocity vector to use with angle_to and dot methods 282 | 283 | ## If below the speed limit, or above the limit but facing away from the velocity, 284 | ## move the player, adding an assisting force if turning. If above the speed limit, 285 | ## and facing the velocity, add a force perpendicular to the velocity and scale 286 | ## it based on where the player is moving in relation to the velocity. 287 | # Get the angle between the velocity and current movement vector and convert it to degrees 288 | var angle = nvel2.angle_to(move2) 289 | var theta = rad_to_deg(angle) # Angle between 2D look and velocity vectors 290 | var is_below_speed_limit: bool = is_below_speed_limit(vel) 291 | var is_facing_velocity: bool = nvel2.dot(move2) >= 0 292 | var direction: Vector3 # vector to be set 90 degrees either to the left or right of the velocity 293 | var scale: float # Scaled from 0 to 1. Used for both turn assist interpolation and vector scaling 294 | # If the angle is to the right of the velocity 295 | if theta > 0 and theta < 90: 296 | direction = nvel.cross(head.transform.basis.y) # Vecor 90 degrees to the right of velocity 297 | scale = clamp(theta / turning_scale, 0, 1) # Turn assist scale 298 | # If the angle is to the left of the velocity 299 | elif theta < 0 and theta > -90: 300 | direction = head.transform.basis.y.cross(nvel) # Vecor 90 degrees to the left of velocity 301 | scale = clamp(-theta / turning_scale, 0, 1) 302 | # Prevent continuous sliding down steep walkable slopes when the player isn't moving. Could be made better with 303 | # debouncing because too high of a force also affects stopping distance noticeably when not on a slope. 304 | if move == Vector3(0, 0, 0) and is_grounded: 305 | move = -vel / (mass * 100 / anti_slide_force) 306 | move(move, state) 307 | # If not pushing into an unwalkable slope 308 | elif steepest_slope_normal.y > walkable_normal: 309 | # If the player is below the speed limit, or is above it, but facing away from the velocity 310 | if is_below_speed_limit or not is_facing_velocity: 311 | # Interpolate between the movement and velocity vectors, scaling with turn assist sensitivity 312 | move = move.lerp(direction, scale) 313 | # If the player is above the speed limit, and looking within 90 degrees of the velocity 314 | else: 315 | move = direction # Set the move vector 90 to the right or left of the velocity vector 316 | move *= scale # Scale the vector. 0 if looking at velocity, up to full magnitude if looking 90 degrees to the side. 317 | move(move, state) 318 | # If pushing into an unwalkable slope, move with unscaled movement vector. Prevents turn assist from pushing the player into the wall. 319 | elif is_below_speed_limit: 320 | move(move, state) 321 | ### End movement 322 | 323 | # Shotgun jump test 324 | if Input.is_action_just_pressed("fire"): 325 | var dir: Vector3 = camera.global_transform.basis.z # Opposite of look direction 326 | state.apply_central_force(dir * 700) 327 | 328 | 329 | ### Functions ### 330 | # Gets the velocity of a contacted rigidbody at the point of contact with the player capsule 331 | ''' 332 | func get_contacted_body_velocity_at_point(contacted_body: RigidBody3D, contact_position: Vector3): 333 | # Global coordinates of contacted body 334 | var body_position = contacted_body.transform.origin 335 | # Global coordinates of the point of contact between the player and contacted body 336 | var global_contact_position = body_position + contact_position 337 | # Calculate local velocity at point (cross product of angular velocity and contact position vectors) 338 | #print(contacted_body.get_angular_velocity()) 339 | var local_vel_at_point = contacted_body.get_angular_velocity().cross( 340 | global_contact_position - body_position - body_position 341 | ) 342 | # Add the current velocity of the contacted body to the velocity at the contacted point 343 | return contacted_body.get_linear_velocity() + local_vel_at_point 344 | ''' 345 | 346 | 347 | # Return 4 cross products of b with a 348 | func cross4(a, b): 349 | return a.cross(b).cross(b).cross(b).cross(b) 350 | 351 | 352 | # Whether a slope is walkable 353 | func is_walkable(normal: float): 354 | return normal >= walkable_normal # Lower normal means steeper slope 355 | 356 | 357 | # Whether the player is below the speed limit in the direction they're traveling 358 | func is_below_speed_limit(vel): 359 | return vel.length() < current_speed_limit 360 | 361 | 362 | # Move the player 363 | func move(move, state): 364 | var draw_start = self.position - Vector3(0, capsule.height / 4, 0) + move # debug 365 | if is_grounded: 366 | var use_normal = Vector3(0,1,0) # For no slope 367 | var closest_contact_idx = null # The index of the contact point closest to the players intended movement vector 368 | # If a contact or contacts exist(s), use the normal at the contact point closest to the player's intended movement vector (for slope detection) 369 | if state.get_contact_count() > 0: 370 | var smallest_angle = null 371 | for i in state.get_contact_count(): 372 | var origin_to_contact: Vector3 = state.get_contact_local_position(i) - self.transform.origin 373 | var angle = origin_to_contact.angle_to(relative_input()) 374 | if closest_contact_idx == null or smallest_angle == null or angle < smallest_angle: 375 | closest_contact_idx = i 376 | smallest_angle = angle 377 | if closest_contact_idx != null: 378 | use_normal = state.get_contact_local_normal(closest_contact_idx) 379 | 380 | move = cross4(move, use_normal) # Get slope to move along based on contact 381 | if debug_lines: 382 | draw_arrow(draw_start, draw_start + move * capsule.radius, Color(1, 0, 0), 3) # debug 383 | state.apply_central_force(move * accel) 384 | # Account for equal and opposite reaction when contacting a RigidBody 385 | if contacted_body != null: 386 | pass #contacted_body.apply_force(state.get_contact_collider_position(0), move * -accel) 387 | else: 388 | if debug_lines: 389 | draw_arrow(draw_start, draw_start + move * capsule.radius, Color(0, 0, 1), 3) # debug 390 | state.apply_central_force(move * air_control) 391 | 392 | 393 | # Set player friction 394 | func set_friction(): 395 | player_physics_material.friction = local_friction 396 | # If moving or not grounded, reduce friction 397 | if not is_grounded: 398 | player_physics_material.friction = local_friction / friction_divider 399 | 400 | 401 | # Get movement vector based on input, relative to the player's head transform 402 | func relative_input(): 403 | # Initialize the movement vector 404 | var move = Vector3() 405 | # Get cumulative input on axes 406 | var input = Vector3() 407 | input.z += int(Input.is_action_pressed("move_forward")) 408 | input.z -= int(Input.is_action_pressed("move_backward")) 409 | input.x += int(Input.is_action_pressed("move_right")) 410 | input.x -= int(Input.is_action_pressed("move_left")) 411 | # Add input vectors to movement relative to the direction the head is facing 412 | move += input.z * -head.transform.basis.z 413 | move += input.x * head.transform.basis.x 414 | # Normalize to prevent stronger diagonal forces 415 | return move.normalized() 416 | 417 | 418 | # Grow the capsule toward the standing height 419 | func grow_capsule(is_done_shrinking, capsule_scale, move_camera): 420 | is_done_shrinking = false 421 | if capsule.height < original_height: 422 | capsule.height += capsule_scale 423 | capsule_mesh.height += capsule_scale 424 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="move" 14 | run/main_scene="res://Scenes/scene1.tscn" 15 | config/features=PackedStringArray("4.3") 16 | config/icon="res://icon.png" 17 | 18 | [autoload] 19 | 20 | Draw3D="*res://Scripts/Draw3D.gd" 21 | 22 | [display] 23 | 24 | window/size/viewport_width=1920 25 | window/size/viewport_height=1080 26 | window/size/borderless=true 27 | window/vsync/vsync_mode=false 28 | 29 | [dotnet] 30 | 31 | project/assembly_name="move" 32 | 33 | [input] 34 | 35 | move_forward={ 36 | "deadzone": 0.5, 37 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 38 | ] 39 | } 40 | move_backward={ 41 | "deadzone": 0.5, 42 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 43 | ] 44 | } 45 | move_left={ 46 | "deadzone": 0.5, 47 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 48 | ] 49 | } 50 | move_right={ 51 | "deadzone": 0.5, 52 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 53 | ] 54 | } 55 | jump={ 56 | "deadzone": 0.5, 57 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 58 | ] 59 | } 60 | fire={ 61 | "deadzone": 0.5, 62 | "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null) 63 | ] 64 | } 65 | crouch={ 66 | "deadzone": 0.5, 67 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194326,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 68 | ] 69 | } 70 | sprint={ 71 | "deadzone": 0.5, 72 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194325,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 73 | ] 74 | } 75 | 76 | [layer_names] 77 | 78 | 3d_render/layer_1="Player" 79 | 80 | [physics] 81 | 82 | 2d/physics_engine="GodotPhysics" 83 | 3d/physics_engine="JoltPhysics3D" 84 | 3d/default_gravity=14.9 85 | common/physics_fps=240 86 | 87 | [rendering] 88 | 89 | environment/defaults/default_environment="res://default_env.tres" 90 | --------------------------------------------------------------------------------