with one click
unity-camera-systems
Unity Camera Systems
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Unity Camera Systems
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Unity ScriptableObject Architecture
Unity Shaders
Unity State Machines
Registers new C# files in resources/manifests/<system>.json (files array + tests.editmode/playmode list) and validates with just validate-registry. Use when creating any new script, adding a new game system, or fixing 'orphan file' CI failures. Trigger phrases: 'add to manifest', 'register file', 'new system', 'validate registry'. Key capabilities: exact JSON manifest format, ACTIVE/DEPRECATED/EXPERIMENTAL status, dependency declarations, test class name mapping for pre-push gating via resolve_module_tests.py. Do NOT use for modifying physics logic or editing game scripts unrelated to registration.
Unity Terrain & Track Creation for RC Racing
Unity Testing, Debugging & QA
| name | unity-camera-systems |
| description | Unity Camera Systems |
Use this skill when setting up cameras, configuring Cinemachine virtual cameras, implementing camera blending, or building state-driven camera rigs in Unity.
// Packages/manifest.json
"com.unity.cinemachine": "3.1.2"
Version Note:
using Unity.Cinemachine (not using Cinemachine). Key renames: CinemachineVirtualCamera -> CinemachineCamera, CinemachineThirdPersonFollow -> ThirdPersonFollow, CinemachineBlendListCamera -> CinemachineSequencerCamera.This guide uses Cinemachine 3.x naming. The 2.x equivalents are noted where they differ significantly.
Cinemachine separates camera logic from the actual Unity Camera:
Unity Camera (with CinemachineBrain)
|
+-- evaluates all active CinemachineCameras
|
+-- picks the highest-priority camera
|
+-- blends between cameras on transitions
CinemachineBrain (on the main Camera): orchestrates blending, picks the active virtual camera. CinemachineCamera (on separate GameObjects): defines how the camera should behave. Only one is "live" at a time.
// Basic setup hierarchy:
// MainCamera (Camera + CinemachineBrain)
// FollowCam (CinemachineCamera + CinemachineFollow + CinemachineRotationComposer)
// OverviewCam (CinemachineCamera + CinemachinePositionComposer)
Tie cameras to Animator states for automatic context switching:
CinemachineStateDrivenCamera:
Animated Target: [Character Animator]
Default Blend: Ease In Out, 0.5s
State-Camera Map:
Idle -> IdleCam (close, low angle)
Running -> RunCam (pulled back, slight lag)
Jumping -> AirCam (wider FOV)
Combat -> CombatCam (over-shoulder)
Each child camera is a full CinemachineCamera with its own body/aim. The state machine selects which is live.
Classic third-person orbit with three height rings:
CinemachineCamera + CinemachineOrbitalFollow + CinemachineRotationComposer:
Orbits:
Top Rig: Height = 4.5, Radius = 1.75
Middle Rig: Height = 2.5, Radius = 3.0
Bottom Rig: Height = 0.4, Radius = 1.3
Spline Curvature: 0.5
The player's vertical input blends between rigs. Horizontal input orbits around the target.
Cinemachine integrates with Timeline for cinematic sequences:
// Triggering a cutscene
[SerializeField] PlayableDirector _cutsceneDirector;
[SerializeField] CinemachineCamera _gameplayCam;
void StartCutscene()
{
_gameplayCam.Priority = 0; // Let timeline cameras take over
_cutsceneDirector.Play();
_cutsceneDirector.stopped += OnCutsceneEnd;
}
void OnCutsceneEnd(PlayableDirector director)
{
_gameplayCam.Priority = 10;
director.stopped -= OnCutsceneEnd;
}
Essential for mouse interaction, raycasting, and targeting:
// Raycast from screen point
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, 100f))
{
Debug.Log($"Hit: {hit.collider.name} at {hit.point}");
}
// Screen to world position at a specific distance
Vector3 worldPos = Camera.main.ScreenToWorldPoint(
new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10f));
// World to screen position (for UI tracking)
Vector3 screenPos = Camera.main.WorldToScreenPoint(target.position);
bool isOnScreen = screenPos.z > 0
&& screenPos.x > 0 && screenPos.x < Screen.width
&& screenPos.y > 0 && screenPos.y < Screen.height;