Skip to main content

freecam

smooth, professional camera control system.

overview

freecam detaches the camera from your character and lets you fly freely. it includes:

  • spring-based smooth movement
  • adjustable speed
  • fov control
  • multi-input support (keyboard, mouse, gamepad)
  • automatic focus distance

how it works

camera detachment

when enabled, freecam:

  1. saves your current camera state
  2. sets camera type to Custom
  3. disables mouse icon
  4. locks mouse behavior to Default
  5. hides core guis (backpack, chat, health, playerlist)
  6. binds movement inputs

movement system

uses spring physics for smooth, natural movement:

VEL_STIFFNESS = 1.5   -- movement smoothing
PAN_STIFFNESS = 1.0 -- rotation smoothing
FOV_STIFFNESS = 4.0 -- fov transition smoothing

the spring system creates acceleration/deceleration curves instead of instant movement.

input processing

every frame:

  1. reads input from keyboard, mouse, gamepad
  2. calculates target velocity and rotation
  3. applies spring physics
  4. updates camera cframe and fov
  5. calculates focus distance

speed system

  • range: 0.01x to 4x
  • default: 1x
  • adjustment: ±0.75 per arrow press
  • sprint multiplier: 0.25x (when shift held)

fov system

  • range: 1° to 120°
  • default: 70°
  • zoom factor: automatically adjusts pan sensitivity based on fov

lower fov = slower perceived rotation higher fov = faster perceived rotation

focus distance

calculates where the camera is "looking" by:

  1. casting 9 rays from viewport corners and center
  2. finding closest intersection point
  3. setting camera focus to that distance

this ensures proper depth sorting and rendering.

controls

see the keybinds page for complete control reference.

technical details

constants

NAV_GAIN = Vector3.new(1, 1, 1) * 64
PAN_GAIN = Vector2.new(0.75, 1) * 8
FOV_GAIN = 300
PITCH_LIMIT = rad(90)
  • NAV_GAIN: movement speed multiplier
  • PAN_GAIN: rotation speed multiplier
  • FOV_GAIN: fov change speed
  • PITCH_LIMIT: prevents camera flipping

spring implementation

function Spring:Update(dt, goal)
local f = self.f * 2 * pi
local p0 = self.p
local v0 = self.v

local offset = goal - p0
local decay = exp(-f * dt)

local p1 = goal + (v0*dt - offset*(f*dt + 1)) * decay
local v1 = (f*dt*(offset*f - v0) + v0) * decay

self.p = p1
self.v = v1

return p1
end

this creates smooth, physics-based transitions.

input handling

freecam binds inputs at high priority to override default camera controls:

ContextActionService:BindActionAtPriority(
"FreecamKeyboard",
Keypress,
false,
INPUT_PRIORITY,
-- keycodes here
)

advanced usage

customizing feel

edit these values in features/freecam.lua:

-- stiffer movement (more responsive)
VEL_STIFFNESS = 3.0

-- looser movement (more floaty)
VEL_STIFFNESS = 0.5

-- faster base speed
NAV_GAIN = Vector3.new(1, 1, 1) * 128

-- higher fov limit
-- change line: cameraFov = clamp(cameraFov + fov*FOV_GAIN*(dt/zoomFactor), 1, 150)

cinematic techniques

slow reveals:

  • speed: 0.1x - 0.3x
  • hold shift for extra control
  • use low fov (30-50°) for compression

fast travel:

  • speed: 3x - 4x
  • high fov (90-120°) for sense of speed
  • plan path beforehand

orbit shots:

  • medium speed (1x - 1.5x)
  • mouse for smooth rotation
  • maintain consistent distance from subject

limitations

freecam cannot currently:

  • record camera paths
  • save positions
  • interpolate between points
  • control depth of field
  • adjust motion blur

these features are planned for future releases.

source code

location: features/freecam.lua

the freecam module is ~500 lines and includes:

  • spring physics system
  • input handling for 3 input types
  • camera state management
  • focus distance calculation

troubleshooting

camera feels laggy

  • increase game fps
  • reduce stiffness values
  • check for conflicting scripts

controls not responding

  • ensure inputs aren't being processed by game
  • check executor injected properly
  • verify no other freecam scripts running

fov stuck

  • press z twice to reset
  • check mouse wheel working
  • try gamepad buttons instead