├── LICENSE ├── LICENSE.txt ├── README.md ├── icon.png ├── icon.svg ├── models ├── AXWing.blend └── AXWing.gltf ├── project.godot ├── scenes └── root.tscn ├── screenshots ├── editorScreenShot1.jpg └── gameplayScreenShot1.jpg ├── scripts ├── math_lib.gd ├── move_along_object_forward.gd ├── player_flight_controller.gd ├── reticle.gd └── smooth_follow.gd └── textures └── SolAsteroidBeltHDRI.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Keith Maggio 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 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Axie Infinity 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Godot3DFlightControls 2 | A template for creating Flight Controls in a 3D scene for Godot! 3 | 4 | Follow the complete tutorial here: https://keithmaggio.wordpress.com/2023/10/14/godot-flight-controls-just-the-way-i-like-it/ 5 | 6 | This project shows how to create a Flight Controller in a similar fashion to Star Fox 64's "All-Range Mode." 7 | 8 | This creates a Flight Control Script, a Gameplay "Plane" that moves along its forward (which can be used to switch between All-Range and Rails, if you wanted), a graphical Reticle that follows 3D objects on a 2D canvas, and a Smooth Follow script for the camera. 9 | 10 | It also creates a Scene putting all this together, with basic models and a WorldEnvironment with a Skybox. 11 | 12 | Enjoy, and reach out to me on my Blog if you have questions! 13 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UtMan88/Godot3DFlightControls/0df10c7aca05b3851b265f493deb7a6f1c1842c0/icon.png -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /models/AXWing.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UtMan88/Godot3DFlightControls/0df10c7aca05b3851b265f493deb7a6f1c1842c0/models/AXWing.blend -------------------------------------------------------------------------------- /models/AXWing.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset":{ 3 | "generator":"Khronos glTF Blender I/O v3.6.27", 4 | "version":"2.0" 5 | }, 6 | "scene":0, 7 | "scenes":[ 8 | { 9 | "name":"Scene", 10 | "nodes":[ 11 | 0 12 | ] 13 | } 14 | ], 15 | "nodes":[ 16 | { 17 | "mesh":0, 18 | "name":"Cube" 19 | } 20 | ], 21 | "materials":[ 22 | { 23 | "doubleSided":true, 24 | "name":"Material", 25 | "pbrMetallicRoughness":{ 26 | "baseColorFactor":[ 27 | 0.800000011920929, 28 | 0.800000011920929, 29 | 0.800000011920929, 30 | 1 31 | ], 32 | "metallicFactor":0, 33 | "roughnessFactor":0.5 34 | } 35 | } 36 | ], 37 | "meshes":[ 38 | { 39 | "name":"Cube", 40 | "primitives":[ 41 | { 42 | "attributes":{ 43 | "POSITION":0, 44 | "NORMAL":1, 45 | "TEXCOORD_0":2 46 | }, 47 | "indices":3, 48 | "material":0 49 | } 50 | ] 51 | } 52 | ], 53 | "accessors":[ 54 | { 55 | "bufferView":0, 56 | "componentType":5126, 57 | "count":518, 58 | "max":[ 59 | 6.230193138122559, 60 | 2.6268248558044434, 61 | 5.711419105529785 62 | ], 63 | "min":[ 64 | -6.230193138122559, 65 | -2.6268248558044434, 66 | -2.7952003479003906 67 | ], 68 | "type":"VEC3" 69 | }, 70 | { 71 | "bufferView":1, 72 | "componentType":5126, 73 | "count":518, 74 | "type":"VEC3" 75 | }, 76 | { 77 | "bufferView":2, 78 | "componentType":5126, 79 | "count":518, 80 | "type":"VEC2" 81 | }, 82 | { 83 | "bufferView":3, 84 | "componentType":5123, 85 | "count":882, 86 | "type":"SCALAR" 87 | } 88 | ], 89 | "bufferViews":[ 90 | { 91 | "buffer":0, 92 | "byteLength":6216, 93 | "byteOffset":0, 94 | "target":34962 95 | }, 96 | { 97 | "buffer":0, 98 | "byteLength":6216, 99 | "byteOffset":6216, 100 | "target":34962 101 | }, 102 | { 103 | "buffer":0, 104 | "byteLength":4144, 105 | "byteOffset":12432, 106 | "target":34962 107 | }, 108 | { 109 | "buffer":0, 110 | "byteLength":1764, 111 | "byteOffset":16576, 112 | "target":34963 113 | } 114 | ], 115 | "buffers":[ 116 | { 117 | "byteLength":18340, 118 | "uri":"data:application/octet-stream;base64,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IwCqAA8AqgCRAKIAoACoAKIAqACkACIAJgClACIApQCpAJAApwCeAJAAngCWALgAtgCvALgArwC6AMEAuQC7AMEAuwDDAKwArgC0AKwAtACyAMcAxAC8ALwAsACtALwArQDHAL0AxgCrAL0AqwCxAL8AwgDFAL8AxQDIAL4AswC1ALUAtwDAALUAwAC+AJ8AoQDPAJ8AzwDOAJQAnQDNAJQAzQDKAAoB6QDTAAoB0wDhAPYA+wDaAPYA2gDYAP4AAwHeAP4A3gDcAAUBDAHiAAUB4gDfANIA1gDZANkA2wDdAN0A4ADSANkA3QDSAO0A9ADXAO0A1wDUAOYA7wDVAOYA1QDRAOcA4wDrAOcA6wDwAO4A6gDxAO4A8QD1APcA8gD4APcA+AD8AP0A+gAAAf0AAAECAQQBAQEIAQQBCAELAQkBBwHlAAkB5QDoAOwA5AAGAQYB/wD5APkA8wDsAAYB+QDsAEgASgAXAUgAFwEUARABEgEWARABFgEaAUkASwAfAR8BGQEVAR8BFQFJAA0BGAEeAQ0BHgEcATQBUgBPAE8AJAEnAU8AJwE0AR0BMAEqAR0BKgEOARsBTABRAFEAMgEuAVEALgEbASUBIAEsASUBLAEpATEBNQEoATEBKAErAQ8BLQEiAQ8BIgERAUMBPwE6AUMBOgFHAUwBQgFGAUwBRgFQATcBOwFBATcBQQE9AVIBTwFFAUUBOQE2AUUBNgFSAUoBUwE4AUoBOAE+AUgBSwFOAUgBTgFRAUkBPAFAAUABRAFNAUABTQFJASEBJgFQACEBUABNABMBIwFOABMBTgBHAI4BaQFUAY4BVAFkAXgBgQFfAXgBXwFbAX4BhwFhAX4BYQFdAYUBjAFjAYUBYwFgAVUBVwFaAVoBXgFiAWIBZQFVAVoBYgFVAXMBegFcAXMBXAFZAWwBcQFYAWwBWAFWAWsBaAFuAWsBbgFwAXIBbwF2AXIBdgF5AXcBdQF9AXcBfQGAAX8BewGDAX8BgwGIAYYBggGJAYYBiQGNAY8BigFmAY8BZgFqAW0BZwGLAYsBhAF8AXwBdAFtAYsBfAFtAckAlAGYAckAmAHLAJABmwGZAZABmQGWAR8BSwDMAMwAmgGdAcwAnQEfAZIBHAEeAZIBHgGcAdAAUgA0ATQBpwGkATQBpAHQAB0BkwGrAR0BqwEwAaMBpQGpAaMBqQGhAS8BqgGmAS8BpgEzAZEBlwGfAZEBnwGoAbkBuwGwAbkBsAG3AcIBxAG8AcIBvAG6Aa0BswG1Aa0BtQGvAb0BxQHIAcgBrgGxAcgBsQG9Ab4BsgGsAb4BrAHHAcAByQHGAcABxgHDAbYBtAG/Ab8BwQG4Ab8BuAG2AaABzgDPAKABzwCiAZUBygDNAJUBzQCeAQMC2gHMAQMCzAHiAe8B0QHTAe8B0wH0AfcB1QHXAfcB1wH8Af4B2AHbAf4B2wEFAtIBzwHLAcsB2QHWAdYB1AHSAcsB1gHSAeYBzQHQAeYB0AHtAd8BygHOAd8BzgHoAeAB6QHkAeAB5AHcAecB7gHqAecB6gHjAfAB9QHxAfAB8QHrAfYB+wH5AfYB+QHzAf0BBAIBAv0BAQL6AQIC4QHeAQIC3gEAAv8B3QHlAeUB7AHyAfIB+AH/AeUB8gH/AQ==" 119 | } 120 | ] 121 | } 122 | -------------------------------------------------------------------------------- /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="Godot3DFlightControls" 14 | run/main_scene="res://scenes/root.tscn" 15 | config/features=PackedStringArray("4.1", "Forward Plus") 16 | config/icon="res://icon.png" 17 | 18 | [dotnet] 19 | 20 | project/assembly_name="Godot3DFlightControls" 21 | 22 | [filesystem] 23 | 24 | import/fbx/enabled=false 25 | -------------------------------------------------------------------------------- /scenes/root.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=13 format=3 uid="uid://de538c62welpc"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://pqy7xl8lj7en" path="res://textures/SolAsteroidBeltHDRI.png" id="1_31hwd"] 4 | [ext_resource type="Script" path="res://scripts/move_along_object_forward.gd" id="2_uqyup"] 5 | [ext_resource type="Script" path="res://scripts/player_flight_controller.gd" id="3_m6gvb"] 6 | [ext_resource type="PackedScene" uid="uid://de52117a3sgq2" path="res://models/AXWing.gltf" id="4_mtrfe"] 7 | [ext_resource type="Script" path="res://scripts/smooth_follow.gd" id="5_b133x"] 8 | [ext_resource type="Script" path="res://scripts/reticle.gd" id="6_pof7r"] 9 | 10 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ks7xt"] 11 | albedo_color = Color(1, 0, 1, 1) 12 | 13 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_jyhku"] 14 | albedo_color = Color(0, 1, 1, 1) 15 | 16 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0tyx0"] 17 | albedo_color = Color(1, 1, 0, 1) 18 | 19 | [sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_hi0hg"] 20 | panorama = ExtResource("1_31hwd") 21 | 22 | [sub_resource type="Sky" id="Sky_ykfqd"] 23 | sky_material = SubResource("PanoramaSkyMaterial_hi0hg") 24 | 25 | [sub_resource type="Environment" id="Environment_x4t8m"] 26 | background_mode = 2 27 | sky = SubResource("Sky_ykfqd") 28 | 29 | [node name="root" type="Node3D"] 30 | 31 | [node name="Scenery" type="Node3D" parent="."] 32 | 33 | [node name="CSGBox3D" type="CSGBox3D" parent="Scenery"] 34 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0) 35 | material_override = SubResource("StandardMaterial3D_ks7xt") 36 | 37 | [node name="CSGBox3D2" type="CSGBox3D" parent="Scenery"] 38 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, 0) 39 | 40 | [node name="CSGBox3D3" type="CSGBox3D" parent="Scenery"] 41 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0, 5) 42 | 43 | [node name="CSGBox3D4" type="CSGBox3D" parent="Scenery"] 44 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0, 5) 45 | material_override = SubResource("StandardMaterial3D_jyhku") 46 | 47 | [node name="CSGBox3D5" type="CSGBox3D" parent="Scenery"] 48 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0, -5) 49 | material_override = SubResource("StandardMaterial3D_0tyx0") 50 | 51 | [node name="CSGBox3D6" type="CSGBox3D" parent="Scenery"] 52 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0, -5) 53 | 54 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="Scenery"] 55 | transform = Transform3D(0.688355, 0.526168, -0.499315, 0, 0.688355, 0.725374, 0.725374, -0.499315, 0.473832, 0, 10, 0) 56 | 57 | [node name="WorldEnvironment" type="WorldEnvironment" parent="Scenery"] 58 | environment = SubResource("Environment_x4t8m") 59 | 60 | [node name="PlayerMovePlane" type="Node3D" parent="." node_paths=PackedStringArray("target")] 61 | script = ExtResource("2_uqyup") 62 | target = NodePath("Player") 63 | speed = 2.0 64 | 65 | [node name="Player" type="Node3D" parent="PlayerMovePlane" node_paths=PackedStringArray("player_model")] 66 | script = ExtResource("3_m6gvb") 67 | player_model = NodePath("AXWing") 68 | 69 | [node name="AimAt" type="Node3D" parent="PlayerMovePlane/Player"] 70 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 10) 71 | 72 | [node name="AXWing" parent="PlayerMovePlane/Player" instance=ExtResource("4_mtrfe")] 73 | transform = Transform3D(-0.1, 0, -8.74228e-09, 0, 0.1, 0, 8.74228e-09, 0, -0.1, 0, 0, 0) 74 | 75 | [node name="PlayerFollower" type="Node3D" parent="." node_paths=PackedStringArray("target")] 76 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -5) 77 | script = ExtResource("5_b133x") 78 | target = NodePath("../PlayerMovePlane") 79 | distance = 2.0 80 | height = 0.75 81 | rotation_damping = 3.25 82 | 83 | [node name="Camera3D" type="Camera3D" parent="PlayerFollower"] 84 | transform = Transform3D(-1, 0, 8.74228e-08, 0, 1, 0, -8.74228e-08, 0, -1, 0, 0, 0) 85 | 86 | [node name="HUD" type="CanvasLayer" parent="."] 87 | 88 | [node name="Reticle" type="Control" parent="HUD" node_paths=PackedStringArray("aim_at_object")] 89 | layout_mode = 3 90 | anchors_preset = 8 91 | anchor_left = 0.5 92 | anchor_top = 0.5 93 | anchor_right = 0.5 94 | anchor_bottom = 0.5 95 | grow_horizontal = 2 96 | grow_vertical = 2 97 | script = ExtResource("6_pof7r") 98 | aim_at_object = NodePath("../../PlayerMovePlane/Player/AimAt") 99 | 100 | [node name="Label" type="Label" parent="HUD/Reticle"] 101 | layout_mode = 1 102 | anchors_preset = 8 103 | anchor_left = 0.5 104 | anchor_top = 0.5 105 | anchor_right = 0.5 106 | anchor_bottom = 0.5 107 | offset_left = -20.0 108 | offset_top = -13.0 109 | offset_right = 20.0 110 | offset_bottom = 13.0 111 | grow_horizontal = 2 112 | grow_vertical = 2 113 | text = "> <" 114 | horizontal_alignment = 1 115 | vertical_alignment = 1 116 | -------------------------------------------------------------------------------- /screenshots/editorScreenShot1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UtMan88/Godot3DFlightControls/0df10c7aca05b3851b265f493deb7a6f1c1842c0/screenshots/editorScreenShot1.jpg -------------------------------------------------------------------------------- /screenshots/gameplayScreenShot1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UtMan88/Godot3DFlightControls/0df10c7aca05b3851b265f493deb7a6f1c1842c0/screenshots/gameplayScreenShot1.jpg -------------------------------------------------------------------------------- /scripts/math_lib.gd: -------------------------------------------------------------------------------- 1 | class_name MathLib 2 | extends Node 3 | 4 | # Source: https://gist.github.com/johnsoncodehk/2ecb0136304d4badbb92bd0c1dbd8bae 5 | static func clamp_angle(angle:float, min:float, max:float) -> float: 6 | var start:float = (min + max) * 0.5 - 180 7 | var floorVal:float = floori((angle - start) / 360) * 360 8 | min += floorVal 9 | max += floorVal 10 | return clampf(angle, min, max) 11 | 12 | 13 | static func smooth_look_at(from:Node3D, target:Node3D, damp:float, delta:float) -> Quaternion: 14 | var look = target.global_transform.looking_at(from.position, Vector3.UP) 15 | return from.quaternion.slerp(Quaternion.from_euler(look.basis.get_euler()), damp * delta) 16 | -------------------------------------------------------------------------------- /scripts/move_along_object_forward.gd: -------------------------------------------------------------------------------- 1 | class_name MoveAlongObjectForward 2 | extends Node3D 3 | 4 | @export var target:Node3D 5 | @export var local_space:bool = false 6 | @export var speed:float = 6.0 7 | 8 | 9 | func smooth_rotation(to_rotation:Vector3, duration:float): 10 | transform.basis = Basis.from_euler(to_rotation) 11 | 12 | 13 | # Called when the node enters the scene tree for the first time. 14 | func _ready(): 15 | pass # Replace with function body. 16 | 17 | 18 | # Called every frame. 'delta' is the elapsed time since the previous frame. 19 | func _process(delta): 20 | if(target): 21 | var forward:Vector3 = Vector3.FORWARD 22 | if (local_space == false) : 23 | forward = target.global_transform.basis.z 24 | else: 25 | forward = target.transform.basis.z 26 | global_translate((forward * speed) * delta) 27 | -------------------------------------------------------------------------------- /scripts/player_flight_controller.gd: -------------------------------------------------------------------------------- 1 | class_name PlayerFlightController 2 | extends Node3D 3 | 4 | @export_subgroup("Speed Control") 5 | @export var normal_speed:float = 2 6 | @export var boost_speed:float = 4 7 | @export var brake_speed:float = 0.01 8 | 9 | @export_subgroup("Banking") 10 | @export var min_pitch:float = -30.0 11 | @export var max_pitch:float = 30.0 12 | @export var min_yaw:float = -90.0 13 | @export var max_yaw:float = 90.0 14 | @export var rotation_smoothing:float = 2.0 15 | 16 | @export_subgroup("Model & Structure") 17 | @export var player_model:Node3D 18 | @onready var _movement_plane:MoveAlongObjectForward = get_parent() 19 | 20 | 21 | # Called when the node enters the scene tree for the first time. 22 | func _ready(): 23 | _movement_plane.speed = normal_speed; 24 | 25 | 26 | # Called every frame. 'delta' is the elapsed time since the previous frame. 27 | func _process(delta): 28 | var speed_delta = ( 29 | Input.get_action_strength("ui_text_caret_page_up") - 30 | Input.get_action_strength("ui_text_caret_page_down") 31 | ) 32 | var horizontal:float = ( 33 | Input.get_action_strength("ui_right") - 34 | Input.get_action_strength("ui_left") 35 | ) 36 | var vertical:float = ( 37 | Input.get_action_strength("ui_down") - 38 | Input.get_action_strength("ui_up") 39 | ) 40 | var speed = clampf(_movement_plane.speed + (speed_delta * delta), brake_speed, boost_speed); 41 | _movement_plane.speed = speed; 42 | _rotation_look(horizontal, vertical, delta) 43 | _horizontal_lean(player_model, horizontal, 80, 50, delta) 44 | 45 | 46 | func _rotation_look(horizontal:float, vertical:float, delta:float): 47 | var aim_rot:Vector3 = _movement_plane.basis.get_euler() 48 | aim_rot.z = 0 49 | aim_rot.y += -horizontal * delta 50 | aim_rot.x += vertical * delta 51 | aim_rot.x = deg_to_rad(MathLib.clamp_angle(rad_to_deg(aim_rot.x), min_pitch, max_pitch)) 52 | _movement_plane.smooth_rotation(aim_rot, rotation_smoothing * delta) 53 | 54 | 55 | func _horizontal_lean(target:Node3D, input_axis:float, lean_limit:float, damp:float, delta:float): 56 | var target_euler_angles = target.transform.basis.get_euler() 57 | var bank = lerp_angle(target_euler_angles.z, input_axis * lean_limit, damp * delta) 58 | target.rotate_object_local(Vector3.FORWARD, deg_to_rad(bank)) 59 | -------------------------------------------------------------------------------- /scripts/reticle.gd: -------------------------------------------------------------------------------- 1 | class_name Reticle 2 | extends Control 3 | 4 | @export var aim_at_object:Node3D 5 | 6 | 7 | # Called when the node enters the scene tree for the first time. 8 | func _ready(): 9 | pass # Replace with function body. 10 | 11 | 12 | # Called every frame. 'delta' is the elapsed time since the previous frame. 13 | func _process(_delta): 14 | var pos = aim_at_object.global_position 15 | var cam = get_tree().root.get_camera_3d() 16 | var screenPos = cam.unproject_position(pos) 17 | global_position = screenPos 18 | -------------------------------------------------------------------------------- /scripts/smooth_follow.gd: -------------------------------------------------------------------------------- 1 | ############# 2 | # Simple SmoothFollow Script 3 | ############# 4 | class_name SmoothFollow 5 | extends Node3D 6 | 7 | # Target we are following 8 | @export var target:Node3D 9 | # The distance in the x-z plane to the target 10 | @export var distance:float = 10.0 11 | # the height we want the camera to be above the target 12 | @export var height:float = 5.0 13 | # Smooth the follow by damping it 14 | @export var position_damping:float = 2.0 15 | # Should we also look at the target? 16 | @export var should_rotate:bool = true 17 | #Smooth the rotation by damping it 18 | @export var rotation_damping:float = 3.0 19 | 20 | 21 | # Called when the node enters the scene tree for the first time. 22 | func _ready(): 23 | pass # Replace with function body. 24 | 25 | 26 | # Called every frame. 'delta' is the elapsed time since the previous frame. 27 | func _process(delta): 28 | if(target): 29 | _follow(delta) 30 | 31 | 32 | func _follow(delta): 33 | # Set the position of the camera on the x-z plane to: 34 | # distance meters behind the target 35 | var offset = -target.global_transform.basis.z * distance 36 | var desired_position = target.position + offset 37 | # Set the height of the camera 38 | desired_position.y += height 39 | # Lerp the final value 40 | set_position(lerp(get_position(), desired_position, position_damping * delta)) 41 | # Always look at the target 42 | if (should_rotate == true): 43 | self.quaternion = MathLib.smooth_look_at(self, target, rotation_damping, delta) 44 | -------------------------------------------------------------------------------- /textures/SolAsteroidBeltHDRI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UtMan88/Godot3DFlightControls/0df10c7aca05b3851b265f493deb7a6f1c1842c0/textures/SolAsteroidBeltHDRI.png --------------------------------------------------------------------------------