blushneybusiness-glitch/roblox-omniskills/rbx-camera-controllers
Claude Code and agent skill by blushneybusiness-glitch/roblox-omniskills
- community
Checking that the SKILL.md file is still in the repository.
Custom camera rigs that feel like top-game defaults — first person, third person, over-shoulder, top-down, and locked-axis cameras with wall-clip handling and respawn safety. Use when the user says "make it first person", "over-the-shoulder camera", "top-down view", "lock the camera", "GTA-style camera", or when the camera jitters, clips through walls, flips over the top, or fights the player's mouse. Do not use for cutscene camera paths — load rbx-camera-cutscene — or for driving cameras — load rbx-vehicles-tuning instead.
Install
npx vskill@latest install blushneybusiness-glitch/roblox-omniskills/rbx-camera-controllersSKILL.md
rbx-camera-controllers
Laws
- Client-only, always. Camera writes from a server Script are silently dropped. Every
rig lives in one LocalScript-driven module. Any gameplay value derived from the camera that reaches the server (aim direction, look target) is re-validated there — dot-product and range checks per rbx-security-anticheat; the client's camera is a claim, not a fact.
- Scriptable only while you own it. Set
CameraType = Enum.CameraType.Scriptableon
rig start, restore Custom in a teardown that runs on every exit path. A player stuck in a dead camera is a session killer.
- One rig at a time. A single controller module with a
setMode(name)switch. Two
scripts writing camera.CFrame produce the classic one-frame flicker war.
- RenderStepped, never Heartbeat. Heartbeat runs after render — one full frame of lag.
Use RunService:BindToRenderStep("Rig", Enum.RenderPriority.Camera.Value - 1, fn).
- Rebind on respawn. Cache
HumanoidRootPart/HeadinsideCharacterAdded, never at
module top level. Stale references after death are the #1 camera bug report.
Recipes
- Third-person follow — pivot = root position + 2 studs up; offset
Vector3.new(0, 4, 12);
desired = CFrame.lookAt(pivot + offset, pivot); smooth with camera.CFrame:Lerp(desired, math.min(dt * 8, 1)). Mouse-wheel zoom: 2 studs per notch, clamped 2–30 (InputChanged only — wheel never fires InputBegan).
- Over-shoulder —
MouseBehavior = LockCenterwhile active; yaw/pitch accumulate from
input.Delta * 0.003 rad/px, pitch clamped ±math.rad(80); offset (right 2.5, up 2, back 8) rotated into yaw space. Wall clip: raycast pivot→camera each frame, on hit pull camera to hitDistance - 0.5.
- First person — `CFrame.new(head.Position) CFrame.Angles(0, yaw, 0)
CFrame.Angles(pitch, 0, 0), pitch clamped ±math.rad(89). Hide the head with LocalTransparencyModifier = 1 — never Transparency`, which replicates to everyone.
- Top-down — camera at
root.Position + Vector3.new(0, 35, 18)looking at the root;
lerp position only (alpha dt * 6), keep rotation fixed so the world never swims.
- Locked-axis (side-scroller) — freeze one world axis of the follow position; the
player moves in a plane, the camera tracks the other two axes at alpha dt * 8.
Sensitivity, zoom limits, and invert-Y are CONFIG-top values wired to a settings screen via rbx-ui-settings, never hardcoded mid-function (contract in luau-contract.md).
Performance budget
One render-step connection for the whole rig; zero table allocations per frame (reuse locals, no closures created in the loop); camera math ≤ 0.1 ms/frame; wall-clip raycast is one ray with a cached RaycastParams; connection disconnected the moment the mode exits.
Load with
rbx-camera-shake — all impact motion composes through its trauma layer, never raw offsets here. rbx-input-bindings when the rig changes what keys do (aim toggle, shoulder swap). rbx-input-mobile for touch-drag look on phones — don't ask, include it. rbx-ui-settings for the sensitivity slider.
AI-tells
- ☐ Camera code in a server Script (silently does nothing)
- ☐ CFrame written without
CameraType = Scriptablefirst (default controller fights it — jitter) - ☐ No pitch clamp — camera flips over the pole
- ☐ Legacy
CFrame.new(pos, lookAt)constructor instead ofCFrame.lookAt - ☐ Heartbeat-driven camera (one frame of drag on every motion)
- ☐ No
CharacterAddedrebind — camera dies on first respawn - ☐ Third-person rig with no wall-clip raycast
- ☐ Head hidden with
Transparencyinstead ofLocalTransparencyModifier
Memory
Read: preferences.md (camera-feel likes/dislikes — smoothing, invert-Y, FOV taste) and the game's projects.md block (existing rig module path, chosen offsets). Write: the shipped controller's module path into module-library.md; final offset/sensitivity values into the game's projects.md block once the user approves the feel.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/rbx-camera-controllers/SKILL.md
Popularity
- 7-day trend score
- 5
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/blushneybusiness-glitch/roblox-omniskills/rbx-camera-controllers)