basic camera movement

This commit is contained in:
Tabby 2025-06-28 23:00:54 +10:00
parent aa7386ab2a
commit 170916456e
14 changed files with 1073 additions and 6 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cphgsibvdxlhx"
path="res://.godot/imported/icon.png-b04047a434905672807d9eea736bf3b2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Free fly camera/Assets/icon.png"
dest_files=["res://.godot/imported/icon.png-b04047a434905672807d9eea736bf3b2.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,70 @@
# Freefly Camera Script for Godot
This is a versatile free-fly camera script for Godot, designed to handle 3D character movement with smooth camera controls. It features adjustable movement settings, mouse sensitivity, sprinting, head rotation clamping, and more. This script is perfect for exploring 3D environments or any other project that requires a free-form camera perspective.
## Features
- **Movement Controls**: Move in 3D space with configurable movement speed and sprinting.
- **Mouse Look**: Control the camera's rotation with mouse input, with optional acceleration and clamping.
- **Collision**: Optionally enable/disable collision detection.
- **Customizable Key Bindings**: Configure movement keys, sprinting, and escape for toggling mouse capture.
- **Head Rotation Clamping**: Option to limit vertical camera rotation for more control.
- **Camera Node**: Easily attach the camera to a character node.
- **Advanced Settings**: Customize settings like whether updates should occur on physics ticks.
## Getting Started
### Prerequisites
- Godot 4.x (tested with Godot 4.3)
- A 3D scene with a `CharacterBody3D` node
### Installation
1. Clone or download this repository to your Godot project folder.
2. In your Godot project, create a new **CharacterBody3D** node (or use an existing one).
3. Attach this script to the **CharacterBody3D** node.
4. Assign a **Camera3D** node to the `camera` variable in the Inspector.
5. Adjust the settings in the Inspector to fit your needs.
### Key Bindings
You can modify the default key bindings in the Inspector for the following actions:
- **Movement**:
- Forward: `W`
- Backward: `S`
- Left: `A`
- Right: `D`
- Up: `Space`
- Down: `Ctrl`
- **Sprint**: `Shift`
- **Escape**: Toggle mouse capture
### Customization
- `movement_speed`: Controls the speed of movement.
- `sprint_multiplier`: Adjusts how much faster you move when sprinting.
- `MOUSE_SENS`: Adjusts mouse sensitivity.
- `MOUSE_ACCEL`: Defines the acceleration factor for the mouse.
- `CLAMP_HEAD_ROTATION_MIN` and `CLAMP_HEAD_ROTATION_MAX`: Set the min/max angles for vertical camera rotation.
- `UPDATE_ON_PHYSICS`: Determines whether the input is processed during the physics step.
### Controls
- **W/A/S/D**: Move the camera around.
- **Mouse**: Look around (with optional head rotation clamping).
- **Shift**: Sprint.
- **Escape**: Toggle mouse capture.
## License
This project is licensed under the **GPL v3.0** License. See the [LICENSE](LICENSE) file for details.
## Attribution
Part of the camera code in this project is derived from the **Basic FPS Player Godot 4.0** project by [sammburr](https://github.com/sammburr/). You can find the original project [here](https://github.com/sammburr/Basic-FPS-Player-GODOT-4.0). Thank you!
## Contributions
Contributions are welcome! If you find bugs or have suggestions, feel free to open an issue or submit a pull request.

View file

@ -0,0 +1,143 @@
extends CharacterBody3D
# Movement Settings
@export_subgroup("Movement settings")
@export var movement_speed : float = 10.0 # Default movement speed
@export var sprint_multiplier: float = 2.0 # Sprint speed multiplier
# Key Bindings
@export_subgroup("Movement keybinds")
@export var KEY_FORWARD: String = "move_forward"
@export var KEY_BACKWARD: String = "move_backward"
@export var KEY_LEFT: String = "move_left"
@export var KEY_RIGHT: String = "move_right"
@export var KEY_UP: String = "move_up"
@export var KEY_DOWN: String = "move_down"
@export var KEY_SPRINT: String = "sprint"
# Mouse Settings
@export_subgroup("Mouse")
@export var MOUSE_ACCEL_STATE := true # Enable mouse acceleration
@export var MOUSE_SENS := 0.005 # Mouse sensitivity
@export var MOUSE_ACCEL := 50 # Mouse acceleration factor
# Head Rotation Clamping
@export_subgroup("Clamp Head Rotation")
@export var CLAMP_HEAD_ROTATION := true # Enable head rotation clamping
@export var CLAMP_HEAD_ROTATION_MIN := -90.0 # Min head rotation
@export var CLAMP_HEAD_ROTATION_MAX := 90.0 # Max head rotation
# Camera Node
@export_subgroup("Camera node")
@export var camera: Camera3D # Camera attached to the character
# Collision Settings (Optional)
@export_subgroup("Collision (Optional)")
@export var collision_state := true # Enable or disable collision
@export var collision: CollisionShape3D # Collision shape for the character
# Advanced Settings
@export_category("Advanced")
@export var UPDATE_ON_PHYSICS := true # Should the update happen on physics ticks?
@export var KEY_ESCAPE: String = "KEY_ESCAPE" # Escape key for toggling mouse capture
# Internal variables for rotation and mouse capture
var rotation_target_player : float
var rotation_target_head : float
var mouse_captured: bool = true
# Called when the node enters the scene tree for the first time
func _ready():
# Toggle collision state if set
if collision != null:
collision.disabled = !collision_state
# If no camera is assigned, create a new one and add it to the node
if camera == null:
camera = Camera3D.new()
add_child(camera)
# Capture the mouse at the start
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
# Process the input every frame if not using physics
func _process(delta: float) -> void:
if !UPDATE_ON_PHYSICS:
handle_input() # Handle player input
rotate_player(delta) # Apply player and camera rotation
# Process input and rotation on physics ticks
func _physics_process(delta: float) -> void:
if UPDATE_ON_PHYSICS:
handle_input()
rotate_player(delta)
# Handle player movement input and apply to the character
func handle_input():
var move_direction = Vector3.ZERO # Initial movement direction is zero
# Toggle mouse capture when the escape key is pressed
if Input.is_action_just_pressed(KEY_ESCAPE):
mouse_captured = not mouse_captured
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if mouse_captured else Input.MOUSE_MODE_VISIBLE
if mouse_captured:
# Movement input for each direction
if Input.is_action_pressed(KEY_FORWARD):
move_direction.z += 1
if Input.is_action_pressed(KEY_BACKWARD):
move_direction.z -= 1
if Input.is_action_pressed(KEY_LEFT):
move_direction.x -= 1
if Input.is_action_pressed(KEY_RIGHT):
move_direction.x += 1
if Input.is_action_pressed(KEY_UP):
move_direction.y += 1
if Input.is_action_pressed(KEY_DOWN):
move_direction.y -= 1
# Normalize the movement vector to ensure consistent speed
move_direction = move_direction.normalized()
# Get the direction relative to the camera orientation
var forward = -camera.global_transform.basis.z
var right = camera.global_transform.basis.x
var up = camera.global_transform.basis.y
# Sprinting multiplier if sprint key is pressed
var speed_mod = sprint_multiplier if Input.is_action_pressed(KEY_SPRINT) else 1.0
velocity = (forward * move_direction.z + right * move_direction.x + up * move_direction.y) * movement_speed * speed_mod
# Move the character
move_and_slide()
# Capture mouse motion input and update rotations
func _input(event):
if Engine.is_editor_hint():
return
# Process mouse motion when the mouse is captured
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
set_rotation_target(event.relative)
# Update the target rotations for the player and camera based on mouse motion
func set_rotation_target(mouse_motion: Vector2):
# Update player rotation based on mouse X movement
rotation_target_player += -mouse_motion.x * MOUSE_SENS
# Update head rotation based on mouse Y movement
rotation_target_head += -mouse_motion.y * MOUSE_SENS
# Clamp the head rotation if enabled
if CLAMP_HEAD_ROTATION:
rotation_target_head = clamp(rotation_target_head, deg_to_rad(CLAMP_HEAD_ROTATION_MIN), deg_to_rad(CLAMP_HEAD_ROTATION_MAX))
# Rotate the player and camera smoothly based on target rotation
func rotate_player(delta):
if MOUSE_ACCEL_STATE:
# Apply spherical interpolation (slerp) for smooth rotation
quaternion = quaternion.slerp(Quaternion(Vector3.UP, rotation_target_player), MOUSE_ACCEL * delta)
camera.quaternion = camera.quaternion.slerp(Quaternion(Vector3.RIGHT, rotation_target_head), MOUSE_ACCEL * delta)
else:
# If mouse acceleration is off, directly set to target rotation
quaternion = Quaternion(Vector3.UP, rotation_target_player)
camera.quaternion = Quaternion(Vector3.RIGHT, rotation_target_head)

View file

@ -0,0 +1 @@
uid://c3tuul2bry2d3

View file

@ -0,0 +1,8 @@
@tool
extends EditorPlugin
func _enter_tree():
add_custom_type("Free fly camera", "CharacterBody3D", preload("Src/free_fly_startup.gd"), preload("Assets/icon.png"))
func _exit_tree():
remove_custom_type("Free fly camera")

View file

@ -0,0 +1 @@
uid://5vj88r3lnd6k

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cffkul203p7mk"
path="res://.godot/imported/icon.png-39dbe21aa156283e14ed29482797b196.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Free fly camera/icon.png"
dest_files=["res://.godot/imported/icon.png-39dbe21aa156283e14ed29482797b196.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,10 @@
[plugin]
name="Free fly camera"
description="Adds the \"Free fly camera\" node.
Currently version V1.0.0, features include:
- Basic movement
- Mouse acceleration"
author="highlife"
version="V1.0.0"
script="free_fly_camera.gd"