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:
- saves your current camera state
- sets camera type to
Custom - disables mouse icon
- locks mouse behavior to
Default - hides core guis (backpack, chat, health, playerlist)
- 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:
- reads input from keyboard, mouse, gamepad
- calculates target velocity and rotation
- applies spring physics
- updates camera cframe and fov
- 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:
- casting 9 rays from viewport corners and center
- finding closest intersection point
- 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 multiplierPAN_GAIN: rotation speed multiplierFOV_GAIN: fov change speedPITCH_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