Skip to content

Instantly share code, notes, and snippets.

@nin-jat
Last active July 12, 2025 07:07
Show Gist options
  • Save nin-jat/fa1b8da52bb519ddc6639027b7b94051 to your computer and use it in GitHub Desktop.
Save nin-jat/fa1b8da52bb519ddc6639027b7b94051 to your computer and use it in GitHub Desktop.
A FreeCamera for godot. Add it to a camera node and add some input actions for WASD. Supports gamepads.

Free-Cam

This is a simple free camera with sensible defaults. It's the simplest implementation I currently know.

Setup

  1. Create a Camera.

  2. Create a godot script for the camera and paste in the provided code.

  3. Edit the input map (Project > Project Settings > Input Map) with some move_forward, move_backward, move_left and move_right actions.

    Example input map settings.

  4. Test and tweak. Change the code, Improve it!

Parameters

default parameters

Acceleration

How fast the camera accelerates to Move Speed and decelerates to zero.

Move Speed

The top speed of the camera.

Mouse Speed

The speed at which the mouse rotates the camera. Smaller is faster.

Note: I need to find a better solution to changing the mouse speed as it appears to be screen size dependant.

Controller Speed

The speed the controller rotates the camera at.

Controller Dead Zone

The dead zone for controllers to eliminate drift.

Demo Video

https://www.youtube.com/watch?v=MvbxaPynvlA

extends Camera
# How fast the camera speeds up to the moveSpeed and slows down to zero.
export var acceleration = 50.0
# The top speed of the camera.
export var moveSpeed = 8.0
# The speed of the mouse input.
export var mouseSpeed = 300.0
# The speed and dead-zone of the controllers input.
export var controllerSpeed = 4.5
export var controllerDeadZone = 0.04
# The current velocity of the camera.
var velocity = Vector3.ZERO
# The look angles and controller Look Input.
var lookAngles = Vector2.ZERO
var controllerLook = Vector2.ZERO
func _process(delta):
# Rotate the camera with the controller.
if controllerLook.length_squared() > controllerDeadZone:
lookAngles -= controllerLook * delta * controllerSpeed
# Limit how much we can look up and down.
lookAngles.y = clamp(lookAngles.y, PI / -2, PI / 2)
set_rotation(Vector3(lookAngles.y, lookAngles.x, 0))
# Get the direction to move from the inputs.
var dir = updateDirection()
# Accelerate or decelerate depending on if we have a direction or not.
if dir.length_squared() > 0:
velocity += dir * acceleration * delta
else:
velocity += velocity.direction_to(Vector3.ZERO) * acceleration * delta
# Kill the velocity if we are close to zero.
if velocity.length() < 0.0005:
velocity = Vector3.ZERO
# Limit the camera's top speed to the moveSpeed then move the camera.
if velocity.length() > moveSpeed:
velocity = velocity.normalized() * moveSpeed
translate(velocity * delta)
# Give the player's mouse back when ESC is pressed.
if Input.is_action_just_pressed("ui_cancel"):
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
func updateDirection():
# Get the direction to move the camera from the input.
var dir = Vector3()
if Input.is_action_pressed("move_forward"):
dir += Vector3.FORWARD
if Input.is_action_pressed("move_backward"):
dir += Vector3.BACK
if Input.is_action_pressed("move_left"):
dir += Vector3.LEFT
if Input.is_action_pressed("move_right"):
dir += Vector3.RIGHT
return dir.normalized()
func _input(event):
# Update the look angles when the mouse moves.
if event is InputEventMouseMotion:
lookAngles -= event.relative / mouseSpeed
# Update the controllerLook when any axis on the controller moves.
if event is InputEventJoypadMotion:
if event.axis == JOY_AXIS_2:
controllerLook.x = event.axis_value
if event.axis == JOY_AXIS_3:
controllerLook.y = event.axis_value
# Steal the mouse from the player when they interact with the window using a
# mouse button.
if event is InputEventMouseButton:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
@JorroIndieDev
Copy link

JorroIndieDev commented Jan 5, 2024

Amazing job, i just updated some variables and some of the code to fit 4.2 and it works wonders

if event is InputEventJoypadMotion: if event.axis == JOY_AXIS_RIGHT_X: controllerLook.x = event.axis_value if event.axis == JOY_AXIS_RIGHT_Y: controllerLook.y = event.axis_value
`# How fast the camera speeds up to the moveSpeed and slows down to zero.
@export var acceleration = 50.0

The top speed of the camera.

@export var moveSpeed = 8.0

The speed of the mouse input.

@export var mouseSpeed = 300.0

The speed and dead-zone of the controllers input.

@export var controllerSpeed = 4.5
@export var controllerDeadZone = 0.04`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment