VERSION 2 HAS ARRIVED!

This commit is contained in:
2023-12-01 22:26:46 -08:00
parent 22d7eca697
commit ff67b7fddf
8 changed files with 612 additions and 1 deletions

View File

@ -1,2 +1,51 @@
# quality-godot-first-person-2 # quality-godot-first-person-2
An actually good first person controller for the Godot Engine (version 2) Actually good first person controller for the Godot Engine.
MIT License (credit Colormatic Studios)
This first person controller was made because there aren't many first person controllers for Godot, and the ones that do exist are pretty bad.
It is highly customizable and comes with many features, QOL, and clean code.
Some parts came from StayAtHomeDev's FPS tutorial. You can find that [here](https://www.youtube.com/playlist?list=PLEHvj4yeNfeF6s-UVs5Zx5TfNYmeCiYwf).
# Directions
Move with WASD, space to jump, shift to sprint, C to crouch.
**FEATURES:**
- In-air momentum
- Motion smoothing
- FOV smoothing
- Head bobbing
- Crouching
- Sprinting
- 2 crosshairs/reticles, one is animated (more to come?)
If you make a cool game with this addon, I would love to hear about it!
# Wiki
To start out, you should probably remap all of the movement keys to your own control set.
You can make this a super basic controller by just disabling everything
**How to change settings**
Click on the character node and there should be settings in the "Feature Settings" group
**How to add animations for a mesh:**
In the `_physics_process` function, add a line to check whether you are walking or aren't walking. You can do this by checking whether `input_dir` is true or false. Optionally, set the animation speed to `speed / base_speed`. This will make it so when the player is walking, your animation speed is 1. If the player is sprinting, your animation goes up and if the player is crouching your animation speed goes down.
In the `toggle_sprint` function, add a line at the end where if `is_sprinting` is true, your animation is set to sprint.
In the `toggle_crouch` function, add a line where if `is_crouching` is true, your animation is set to crouch.
To check if the player is in the air, add a line in the `_physics_process` function where it says `if not is_on_floor():`set your animation to falling/in the air. Add an else statement to change it to the normal state.
**How to change reticles (crosshairs)**
- Find the folder at `res://addons/fpc/reticles`
- Pick one and add it to the `UserInterface` node in the character scene. You may need to right click on the character and enable "Editable Children".
- Set the Character value to your character node (it's under the Nodes group)
- Change the `anchors_preset` value on the reticle to Center
**How to create a new reticle**
- Choose a reticle to base it off of
- Open that reticle and save it as a new reticle
- Edit the reticle to your needs
- Follow the "how to change reticles" directions to use it

181
addons/fpc/character.gd Normal file
View File

@ -0,0 +1,181 @@
extends CharacterBody3D
# TODO: Add descriptions for each value
@export_category("Character")
@export var base_speed : float = 3.0
@export var sprint_speed : float = 6.0
@export var crouch_speed : float = 1.0
@export var acceleration : float = 10.0
@export var jump_velocity : float = 4.5
@export var mouse_sensitivity : float = 0.1
@export_group("Nodes")
@export var HEAD : Node3D
@export var CAMERA : Camera3D
@export var CAMERA_ANIMATION : AnimationPlayer
@export_group("Controls")
# We are using UI controls because they are built into Godot Engine so they can be used right away
@export var JUMP : String = "ui_accept"
@export var LEFT : String = "ui_left"
@export var RIGHT : String = "ui_right"
@export var FORWARD : String = "ui_up"
@export var BACKWARD : String = "ui_down"
@export var PAUSE : String = "ui_cancel"
@export var CROUCH : String
@export var SPRINT : String
@export_group("Feature Settings")
@export var immobile : bool = false
@export var jumping_enabled : bool = true
@export var in_air_momentum : bool = true
@export var motion_smoothing : bool = true
@export var sprint_enabled : bool = true
@export var crouch_enabled : bool = true
@export_enum("Hold to Crouch", "Toggle Crouch") var crouch_mode : int = 0
@export_enum("Hold to Sprint", "Toggle Sprint") var sprint_mode : int = 0
@export var dynamic_fov : bool = true
@export var continuous_jumping : bool = true
@export var view_bobbing : bool = true
# Member variables
var speed : float = base_speed
var is_crouching : bool = false
var is_sprinting : bool = false
# Get the gravity from the project settings to be synced with RigidBody nodes
var gravity : float = ProjectSettings.get_setting("physics/3d/default_gravity") # Don't set this as a const, see the gravity section in _physics_process
func _ready():
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _physics_process(delta):
# Add some debug data
$UserInterface/DebugPanel.add_property("Movement Speed", speed, 1)
$UserInterface/DebugPanel.add_property("Velocity", get_real_velocity(), 2)
# Gravity
#gravity = ProjectSettings.get_setting("physics/3d/default_gravity") # If the gravity changes during your game, uncomment this code
if not is_on_floor():
velocity.y -= gravity * delta
handle_jumping()
var input_dir = Vector2.ZERO
if !immobile:
input_dir = Input.get_vector(LEFT, RIGHT, FORWARD, BACKWARD)
handle_movement(delta, input_dir)
toggle_crouch()
toggle_sprint(input_dir)
if is_crouching:
speed = crouch_speed
elif is_sprinting:
speed = sprint_speed
else:
speed = base_speed
if view_bobbing:
headbob_animation(input_dir)
func handle_jumping():
if jumping_enabled:
if continuous_jumping:
if Input.is_action_pressed(JUMP) and is_on_floor():
velocity.y += jump_velocity
else:
if Input.is_action_just_pressed(JUMP) and is_on_floor():
velocity.y += jump_velocity
func handle_movement(delta, input_dir):
var direction = input_dir.rotated(-HEAD.rotation.y)
direction = Vector3(direction.x, 0, direction.y)
move_and_slide()
if in_air_momentum:
if is_on_floor(): # Don't lerp y movement
if motion_smoothing:
velocity.x = lerp(velocity.x, direction.x * speed, acceleration * delta)
velocity.z = lerp(velocity.z, direction.z * speed, acceleration * delta)
else:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
else:
if motion_smoothing:
velocity.x = lerp(velocity.x, direction.x * speed, acceleration * delta)
velocity.z = lerp(velocity.z, direction.z * speed, acceleration * delta)
else:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
func _process(delta):
$UserInterface/DebugPanel.add_property("FPS", 1.0/delta, 0)
if Input.is_action_just_pressed(PAUSE):
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
elif Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _unhandled_input(event):
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
HEAD.rotation_degrees.y -= event.relative.x * mouse_sensitivity
HEAD.rotation_degrees.x -= event.relative.y * mouse_sensitivity
HEAD.rotation.x = clamp(HEAD.rotation.x, deg_to_rad(-90), deg_to_rad(90))
func toggle_crouch():
if crouch_enabled:
if crouch_mode == 0:
is_crouching = Input.is_action_pressed(CROUCH)
elif crouch_mode == 1:
if Input.is_action_just_pressed(CROUCH):
is_crouching = !is_crouching
# Replace with your own crouch animation code
if is_crouching:
$Collision.scale.y = lerp($Collision.scale.y, 0.75, 0.2)
else:
$Collision.scale.y = lerp($Collision.scale.y, 1.0, 0.2)
func toggle_sprint(moving):
if sprint_enabled:
if sprint_mode == 0:
if !is_crouching: # Crouching takes priority over sprinting
is_sprinting = Input.is_action_pressed(SPRINT)
else:
is_sprinting = false # Fix a bug where if you are sprinting and then crouch then let go of the sprinting button you keep sprinting
elif sprint_mode == 1:
if Input.is_action_just_pressed(SPRINT):
if !is_crouching:
is_sprinting = !is_sprinting
else:
is_sprinting = false
if dynamic_fov:
if is_sprinting and moving:
CAMERA.fov = lerp(CAMERA.fov, 85.0, 0.3)
else:
CAMERA.fov = lerp(CAMERA.fov, 75.0, 0.3)
func headbob_animation(moving):
if moving and is_on_floor():
CAMERA_ANIMATION.play("headbob")
CAMERA_ANIMATION.speed_scale = speed / base_speed
else:
CAMERA_ANIMATION.play("RESET")

124
addons/fpc/character.tscn Normal file
View File

@ -0,0 +1,124 @@
[gd_scene load_steps=12 format=3 uid="uid://cc1m2a1obsyn4"]
[ext_resource type="Script" path="res://addons/fpc/character.gd" id="1_0t4e8"]
[ext_resource type="PackedScene" uid="uid://3mij3cjhkwsm" path="res://addons/fpc/reticles/reticle_1.tscn" id="2_uuexm"]
[ext_resource type="PackedScene" uid="uid://coqpusufa8a6k" path="res://addons/fpc/reticles/reticle_0.tscn" id="3_ce64v"]
[ext_resource type="Script" path="res://addons/fpc/debug.gd" id="3_x1wcc"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kp17n"]
albedo_color = Color(0.909804, 0.596078, 0, 1)
clearcoat_enabled = true
clearcoat_roughness = 0.2
[sub_resource type="CapsuleMesh" id="CapsuleMesh_jw1de"]
material = SubResource("StandardMaterial3D_kp17n")
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_uy03j"]
[sub_resource type="Animation" id="Animation_gh776"]
resource_name = "RESET"
length = 0.001
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Camera:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector3(0, 0, 0)]
}
[sub_resource type="Animation" id="Animation_lrqmv"]
resource_name = "headbob"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Camera:position")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.25, 0.5, 0.75, 1),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
"update": 0,
"values": [Vector3(0, 0, 0), Vector3(-0.05, -0.05, 0), Vector3(0, 0, 0), Vector3(0.05, -0.05, 0), Vector3(0, 0, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_o0unb"]
_data = {
"RESET": SubResource("Animation_gh776"),
"headbob": SubResource("Animation_lrqmv")
}
[sub_resource type="Theme" id="Theme_wdf0f"]
MarginContainer/constants/margin_bottom = 10
MarginContainer/constants/margin_left = 10
MarginContainer/constants/margin_right = 10
MarginContainer/constants/margin_top = 10
[node name="Character" type="CharacterBody3D" node_paths=PackedStringArray("HEAD", "CAMERA", "CAMERA_ANIMATION")]
script = ExtResource("1_0t4e8")
HEAD = NodePath("Head")
CAMERA = NodePath("Head/Camera")
CAMERA_ANIMATION = NodePath("Head/camera_animation")
CROUCH = "crouch"
SPRINT = "sprint"
[node name="Mesh" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
mesh = SubResource("CapsuleMesh_jw1de")
[node name="Collision" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("CapsuleShape3D_uy03j")
[node name="Head" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
[node name="Camera" type="Camera3D" parent="Head"]
transform = Transform3D(0.999511, 0.000977888, -0.0312559, 0, 0.999511, 0.0312712, 0.0312712, -0.0312559, 0.999022, 0, 0, 0)
[node name="camera_animation" type="AnimationPlayer" parent="Head"]
libraries = {
"": SubResource("AnimationLibrary_o0unb")
}
blend_times = [&"RESET", &"RESET", 0.5, &"RESET", &"headbob", 0.5, &"headbob", &"RESET", 0.5]
[node name="UserInterface" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1
[node name="Reticle_0" parent="UserInterface" instance=ExtResource("3_ce64v")]
visible = false
layout_mode = 1
[node name="Reticle_1" parent="UserInterface" node_paths=PackedStringArray("reticle_lines", "character") instance=ExtResource("2_uuexm")]
layout_mode = 1
reticle_lines = [NodePath("top"), NodePath("left"), NodePath("right"), NodePath("bottom")]
character = NodePath("../..")
[node name="DebugPanel" type="PanelContainer" parent="UserInterface"]
layout_mode = 0
offset_left = 10.0
offset_top = 10.0
offset_right = 453.0
offset_bottom = 50.0
theme = SubResource("Theme_wdf0f")
script = ExtResource("3_x1wcc")
[node name="MarginContainer" type="MarginContainer" parent="UserInterface/DebugPanel"]
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="UserInterface/DebugPanel/MarginContainer"]
layout_mode = 2
[editable path="UserInterface/Reticle_1"]

18
addons/fpc/debug.gd Normal file
View File

@ -0,0 +1,18 @@
extends PanelContainer
func _process(delta):
if visible:
pass
func add_property(title:String, value, order):
var target
target = $MarginContainer/VBoxContainer.find_child(title, true, false)
if !target:
target = Label.new()
$MarginContainer/VBoxContainer.add_child(target)
target.name = title
target.text = title + ": " + str(value)
elif visible:
target.text = title + ": " + str(value)
$MarginContainer/VBoxContainer.move_child(target, order)

View File

@ -0,0 +1,37 @@
[gd_scene load_steps=2 format=3 uid="uid://coqpusufa8a6k"]
[sub_resource type="GDScript" id="GDScript_10f85"]
script/source = "extends CenterContainer
@export_category(\"Reticle\")
@export_group(\"Nodes\")
@export var character : CharacterBody3D
@export_group(\"Settings\")
@export var dot_size : int = 1
@export var dot_color : Color = Color.WHITE
func _process(_delta):
if visible: # If the reticle is disabled (not visible), don't bother updating it
update_reticle_settings()
func update_reticle_settings():
$dot.scale.x = dot_size
$dot.scale.y = dot_size
$dot.color = dot_color
"
[node name="Reticle" type="CenterContainer"]
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
script = SubResource("GDScript_10f85")
[node name="dot" type="Polygon2D" parent="."]
polygon = PackedVector2Array(-1, -1, 1, -1, 1, 1, -1, 1)

View File

@ -0,0 +1,103 @@
[gd_scene load_steps=2 format=3 uid="uid://3mij3cjhkwsm"]
[sub_resource type="GDScript" id="GDScript_a8kpl"]
script/source = "extends CenterContainer
@export_category(\"Reticle\")
@export_group(\"Nodes\")
@export var reticle_lines : Array[Line2D]
@export var character : CharacterBody3D
@export_group(\"Animate\")
@export var animated_reticle : bool = true
@export var reticle_speed : float = 0.5
@export var reticle_spread : float = 4.0
@export_group(\"Dot Settings\")
@export var dot_size : int = 1
@export var dot_color : Color = Color.WHITE
@export_group(\"Line Settings\")
@export var line_color : Color = Color.WHITE
@export var line_width : int = 2
@export var line_length : int = 10
@export var line_distance : int = 5
@export_enum(\"None\", \"Round\") var cap_mode : int = 0
func _process(_delta):
if visible: # If the reticle is disabled (not visible), don't bother updating it
update_reticle_settings()
if animated_reticle:
animate_reticle_lines()
func animate_reticle_lines():
var vel = character.get_real_velocity()
var origin = Vector3(0,0,0)
var pos = Vector2(0,0)
var speed = origin.distance_to(vel)
reticle_lines[0].position = lerp(reticle_lines[0].position, pos + Vector2(0, -speed * reticle_spread), reticle_speed)
reticle_lines[1].position = lerp(reticle_lines[1].position, pos + Vector2(-speed * reticle_spread, 0), reticle_speed)
reticle_lines[2].position = lerp(reticle_lines[2].position, pos + Vector2(speed * reticle_spread, 0), reticle_speed)
reticle_lines[3].position = lerp(reticle_lines[3].position, pos + Vector2(0, speed * reticle_spread), reticle_speed)
func update_reticle_settings():
# Dot
$dot.scale.x = dot_size
$dot.scale.y = dot_size
$dot.color = dot_color
# Lines
for line in reticle_lines:
line.default_color = line_color
line.width = line_width
if cap_mode == 0:
line.begin_cap_mode = Line2D.LINE_CAP_NONE
line.end_cap_mode = Line2D.LINE_CAP_NONE
elif cap_mode == 1:
line.begin_cap_mode = Line2D.LINE_CAP_ROUND
line.end_cap_mode = Line2D.LINE_CAP_ROUND
# Please someone find a better way to do this
reticle_lines[0].points[0].y = -line_distance
reticle_lines[0].points[1].y = -line_length - line_distance
reticle_lines[1].points[0].x = -line_distance
reticle_lines[1].points[1].x = -line_length - line_distance
reticle_lines[2].points[0].x = line_distance
reticle_lines[2].points[1].x = line_length + line_distance
reticle_lines[3].points[0].y = line_distance
reticle_lines[3].points[1].y = line_length + line_distance
"
[node name="Reticle" type="CenterContainer"]
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
script = SubResource("GDScript_a8kpl")
[node name="dot" type="Polygon2D" parent="."]
polygon = PackedVector2Array(-1, -1, 1, -1, 1, 1, -1, 1)
[node name="top" type="Line2D" parent="."]
points = PackedVector2Array(0, -5, 0, -15)
width = 2.0
[node name="left" type="Line2D" parent="."]
points = PackedVector2Array(-5, 0, -15, 0)
width = 2.0
[node name="right" type="Line2D" parent="."]
points = PackedVector2Array(5, 0, 15, 0)
width = 2.0
[node name="bottom" type="Line2D" parent="."]
points = PackedVector2Array(0, 5, 0, 15)
width = 2.0

View File

@ -11,5 +11,55 @@ config_version=5
[application] [application]
config/name="first person controller 2.0" config/name="first person controller 2.0"
run/main_scene="res://test_world.tscn"
config/features=PackedStringArray("4.1", "Forward Plus") config/features=PackedStringArray("4.1", "Forward Plus")
config/icon="res://icon.svg" config/icon="res://icon.svg"
[display]
window/size/mode=2
[input]
ui_left={
"deadzone": 0.5,
"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":4194319,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null)
]
}
ui_right={
"deadzone": 0.5,
"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":4194321,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null)
]
}
ui_up={
"deadzone": 0.5,
"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":4194320,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"echo":false,"script":null)
]
}
ui_down={
"deadzone": 0.5,
"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":4194322,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null)
]
}
crouch={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"echo":false,"script":null)
]
}
sprint={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}

49
test_world.tscn Normal file
View File

@ -0,0 +1,49 @@
[gd_scene load_steps=9 format=3 uid="uid://cs4drhmc1bql5"]
[ext_resource type="PackedScene" uid="uid://cc1m2a1obsyn4" path="res://addons/fpc/character.tscn" id="1_e18vq"]
[sub_resource type="Gradient" id="Gradient_ur0vy"]
colors = PackedColorArray(0, 0.476245, 0.0193456, 1, 0.360494, 0.612721, 0.119744, 1)
[sub_resource type="FastNoiseLite" id="FastNoiseLite_jd3pw"]
frequency = 0.005
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_7akuf"]
width = 1024
height = 1024
in_3d_space = true
color_ramp = SubResource("Gradient_ur0vy")
noise = SubResource("FastNoiseLite_jd3pw")
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_67ysu"]
albedo_texture = SubResource("NoiseTexture2D_7akuf")
[sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_edcox"]
ground_color = Color(0.160784, 0.815686, 0.905882, 1)
[sub_resource type="Sky" id="Sky_2iust"]
sky_material = SubResource("PhysicalSkyMaterial_edcox")
[sub_resource type="Environment" id="Environment_20rw3"]
background_mode = 2
sky = SubResource("Sky_2iust")
tonemap_mode = 1
ssao_enabled = true
[node name="test_world" type="Node3D"]
[node name="character" parent="." instance=ExtResource("1_e18vq")]
[node name="CSGBox3D" type="CSGBox3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, 0)
use_collision = true
size = Vector3(10, 1, 10)
material = SubResource("StandardMaterial3D_67ysu")
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_20rw3")
[node name="sun" type="DirectionalLight3D" parent="."]
transform = Transform3D(0.87959, -0.436605, 0.188936, 0, 0.397148, 0.917755, -0.475732, -0.807248, 0.349328, 0, 0, 0)
light_energy = 4.0
shadow_enabled = true