一键导入
cinemachine
Cinemachine camera system — virtual cameras, FreeLook, blending, noise profiles, state-driven cameras, confiner, follow/aim behaviors.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Cinemachine camera system — virtual cameras, FreeLook, blending, noise profiles, state-driven cameras, confiner, follow/aim behaviors.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Card game patterns — deck building, hand management, turn structure, card effects, battlefield zones
Racing game patterns — vehicle physics, track design, lap tracking, AI opponents, drift mechanics
Roguelike/roguelite patterns — procedural dungeons, permadeath, meta-progression, loot systems, turn-based or real-time
Tower defense game patterns — placement grids, enemy pathing, wave spawning, tower upgrades, economy
Endless runner architecture — procedural chunk spawning, lane-based or free movement, obstacle patterns, speed ramping, coin/collectible systems, distance scoring.
Hyper-casual mobile game architecture — one-tap/swipe controls, instant onboarding, short sessions, ad monetization, minimalist visuals, level progression, score systems.
| name | cinemachine |
| description | Cinemachine camera system — virtual cameras, FreeLook, blending, noise profiles, state-driven cameras, confiner, follow/aim behaviors. |
| globs | ["**/*Cinemachine*","**/*Camera*.cs","**/*Cam*.cs"] |
CinemachineBrain component to Main CameraBody (follow):
Transposer — 3D offset follow (configurable damping)Framing Transposer — 2D/screen-space follow (dead zone, soft zone)Orbital Transposer — orbit around target (user input rotates)Tracked Dolly — follow a pathAim (look at):
Composer — keep target in frame with dead/soft zonesGroup Composer — frame a group of targetsHard Look At — no damping, instant lookPOV — player-controlled rotation (FPS)Virtual Camera:
Body: Framing Transposer
- Screen X/Y: 0.5 (center)
- Dead Zone Width: 0.1, Height: 0.1
- Damping: X=1, Y=0.5
Follow: Player Transform
Add Extension: CinemachineConfiner2D
- Bounding Shape: PolygonCollider2D (room bounds)
FreeLook Camera:
Follow: Player Transform
Look At: Player Head/Chest
Top/Middle/Bottom Rig:
- Height, Radius per rig
- Composer aim in each rig
X Axis: Input from mouse/stick (orbiting)
Y Axis: Input from mouse/stick (elevation)
State-Driven Camera:
Animated Target: Player Animator
States:
Idle → VCam_Idle (wide shot)
Run → VCam_Run (further back)
Combat → VCam_Combat (over shoulder)
// Source: generates impulse
[SerializeField] private CinemachineImpulseSource m_ImpulseSource;
public void OnExplosion()
{
m_ImpulseSource.GenerateImpulse();
}
Add CinemachineImpulseListener extension to virtual cameras that should respond.
Add CinemachineBasicMultiChannelPerlin to virtual camera:
6D Shake or Handheld_normal_mild// Switch cameras by priority
m_CombatCamera.Priority = 20; // Higher = active
m_ExploreCamera.Priority = 10;
// Change follow target
m_VirtualCamera.Follow = newTarget;
m_VirtualCamera.LookAt = newTarget;
CinemachineConfiner2D + PolygonCollider2D (set collider to trigger, non-physics layer)CinemachineConfiner + BoxCollider or MeshCollider volumeDamping controls how quickly the camera follows the target. Lower values mean snappier response, higher values add lag for a smoother feel.
2D Platformer:
Third Person Action:
Top-Down / RTS:
Driving / Racing:
Lookahead shifts the camera ahead of the target's velocity so the player sees more of what is coming.
Lookahead Time: 0.3 to 0.7 seconds for platformers, 0 for combat gamesLookahead Smoothing: 5 to 15 — higher values smooth out jitter but add latency| Need | Choose |
|---|---|
| 2D game or side-scroller | Framing Transposer — works in screen space |
| 3D game with offset follow | Transposer — works in world space |
| Camera must maintain screen-space framing | Framing Transposer |
| Camera offset defined in meters from target | Transposer |
| Need dead zone and soft zone in screen space | Framing Transposer |
| Camera position relative to target regardless of screen size | Transposer |
Create a CinemachineBlenderSettings asset (Assets > Create > Cinemachine > Blender Settings) to define per-transition blends.
Assign the asset to the CinemachineBrain.CustomBlends field.
Each entry specifies: From Camera, To Camera, Blend Style, and Blend Time.
Blend styles:
EaseInOut — smooth acceleration and deceleration, best defaultEaseIn — soft start, abrupt end, good for entering actionEaseOut — abrupt start, soft end, good for settling into a sceneLinear — constant speed, useful for mechanical/UI camerasHardIn — fast start, used for impact momentsHardOut — fast end, used to snap into positionCustom — provide your own AnimationCurve for full controlOn CinemachineBrain, the DefaultBlend applies when no custom blend exists.
When multiple cameras activate simultaneously:
CinemachineBlendListCamera to sequence multiple cameras in a scripted orderWhen a blend is in progress and a new camera activates:
using UnityEngine;
using Unity.Cinemachine;
using VContainer;
// Camera mode enum shared between systems
public enum CameraMode
{
Exploration,
Combat,
Dialogue
}
// System that manages camera state transitions
public sealed class CameraStateSystem : System.IDisposable
{
private readonly CinemachineCamera m_ExplorationCam;
private readonly CinemachineCamera m_CombatCam;
private readonly CinemachineCamera m_DialogueCam;
private const int k_ActivePriority = 20;
private const int k_InactivePriority = 0;
private CameraMode m_CurrentMode = CameraMode.Exploration;
[Inject]
public CameraStateSystem(
[Inject(Id = "ExplorationCam")] CinemachineCamera explorationCam,
[Inject(Id = "CombatCam")] CinemachineCamera combatCam,
[Inject(Id = "DialogueCam")] CinemachineCamera dialogueCam)
{
m_ExplorationCam = explorationCam;
m_CombatCam = combatCam;
m_DialogueCam = dialogueCam;
SetMode(CameraMode.Exploration);
}
public void SetMode(CameraMode mode)
{
m_CurrentMode = mode;
m_ExplorationCam.Priority = mode == CameraMode.Exploration ? k_ActivePriority : k_InactivePriority;
m_CombatCam.Priority = mode == CameraMode.Combat ? k_ActivePriority : k_InactivePriority;
m_DialogueCam.Priority = mode == CameraMode.Dialogue ? k_ActivePriority : k_InactivePriority;
}
public CameraMode CurrentMode => m_CurrentMode;
public void Dispose() { }
}
Use CinemachineStateDrivenCamera when camera changes map directly to animation states.
CinemachineStateDrivenCamera:
Animated Target: Character Animator
Default Blend: EaseInOut 1.0s
State-Camera Pairs:
"Idle" → VCam_Idle (wide, slow follow)
"Run" → VCam_Run (pulled back, higher damping)
"Attack" → VCam_Attack (over-shoulder, tight framing)
"Hurt" → VCam_Hurt (slight zoom, screen shake via noise)
"Death" → VCam_Death (slow dolly out, cut blend)
Each child camera can have its own body, aim, noise, and extensions. The state-driven parent handles activation based on animator state.
For systems that do not map cleanly to animator states, manage priorities directly.
// Reacting to a MessagePipe message to switch camera
public sealed class CombatCameraResponder : System.IDisposable
{
private readonly CameraStateSystem m_CameraState;
private readonly System.IDisposable m_Subscription;
[Inject]
public CombatCameraResponder(
CameraStateSystem cameraState,
ISubscriber<CombatEnteredMessage> combatEntered)
{
m_CameraState = cameraState;
m_Subscription = combatEntered.Subscribe(OnCombatEntered);
}
private void OnCombatEntered(CombatEnteredMessage message)
{
m_CameraState.SetMode(CameraMode.Combat);
}
public void Dispose() => m_Subscription.Dispose();
}
Use CinemachineImpulseChannels to separate different shake sources. Each source and listener has a channel mask (bitmask). A listener only responds to impulses on matching channels.
Channel 1: Combat (weapon impacts, explosions)
Channel 2: Environment (earthquakes, collapsing structures)
Channel 3: UI Feedback (menu confirm, error shake)
Configure channel mask on both CinemachineImpulseSource and CinemachineImpulseListener to isolate which cameras react to which events.
Instant impulse (explosion, hit):
6D ShakeSustained impulse (earthquake, engine rumble):
Handheld_normal_mildDirectional impulse (recoil):
CinemachineImpulseSource.GenerateImpulse(Vector3 velocity) to specify directionpublic sealed class DistanceScaledImpulse : MonoBehaviour
{
[SerializeField] private CinemachineImpulseSource m_ImpulseSource;
[SerializeField] private float m_MaxDistance = 30f;
[SerializeField] private float m_MaxAmplitude = 2f;
public void TriggerAtPosition(Vector3 sourcePosition, Vector3 listenerPosition)
{
float distance = Vector3.Distance(sourcePosition, listenerPosition);
float normalizedDistance = Mathf.Clamp01(distance / m_MaxDistance);
// Inverse-square falloff
float amplitude = m_MaxAmplitude * (1f - normalizedDistance * normalizedDistance);
if (amplitude > 0.01f)
{
m_ImpulseSource.GenerateImpulse(amplitude);
}
}
}
On the CinemachineImpulseListener extension:
Gain: multiplier on incoming impulse amplitude (0 = deaf, 1 = normal, 2 = amplified)Use 2D Distance: ignore Y axis for distance attenuation (good for side-scrollers)Channel Mask: bitmask to filter which impulse channels this listener reacts toA FreeLook camera uses three orbital rigs stacked vertically: Top, Middle, Bottom. The player orbits the character by moving the Y axis between rigs and the X axis around the character.
Top Rig: Height 4.5, Radius 1.5 (bird's-eye, tight orbit)
Middle Rig: Height 2.5, Radius 4.0 (default gameplay view)
Bottom Rig: Height 0.4, Radius 4.5 (low angle, dramatic)
Each rig has its own Composer aim settings. The camera interpolates between rigs as the Y axis changes.
X Axis (horizontal orbit):
Max Speed: 300 (degrees per second with full stick deflection)
Accel Time: 0.1 (seconds to reach max speed)
Decel Time: 0.15 (seconds to stop)
Invert: false (platform convention)
Y Axis (vertical rig blend):
Max Speed: 2.0 (blend units per second, 0 = bottom rig, 1 = top rig)
Accel Time: 0.1
Decel Time: 0.15
Invert: true (push up to look down is common in third-person)
Recentering automatically moves the camera behind the character when input stops.
Wait Time: seconds of no input before recentering starts (1.0 to 3.0)Recentering Time: seconds to complete the recenter (0.5 to 2.0)using UnityEngine;
using Unity.Cinemachine;
public sealed class RoomConfinerSwapper : MonoBehaviour
{
[SerializeField] private CinemachineConfiner2D m_Confiner;
public void SwitchToRoom(PolygonCollider2D roomBounds)
{
m_Confiner.BoundingShape2D = roomBounds;
m_Confiner.InvalidateBoundingShapeCache();
}
}
Call InvalidateBoundingShapeCache() whenever the bounding shape reference or geometry changes. Without this call the confiner uses stale data.
For games with discrete rooms (metroidvania, dungeon crawler):
PolygonCollider2D on a dedicated "CameraBounds" layer (set as trigger)SwitchToRoom with the new colliderBy default, switching the confiner boundary causes a snap. To smooth it:
Damping value on the confiner extension during the switch, then restore itCinemachineConfiner2D.Damping controls how quickly the camera is pushed back inside bounds. A value of 1 to 3 provides a smooth pull rather than a hard clamp.Inset the confiner polygon so the camera does not push important content behind UI elements:
PolygonCollider2D points inward by the UI margin (e.g., 1 unit on each side)Screen.safeAreaSelect the Main Camera (with CinemachineBrain) in Play mode to see:
Enable CinemachineBrain.ShowDebugText in the inspector to display the active camera name on screen during play mode.
In the Scene view, select a Virtual Camera and click the "Solo" button in the Cinemachine inspector. This forces the Game view to use that camera regardless of priority. Useful for tuning individual camera settings without triggering blend logic.
Remember to un-solo before testing transitions.