From unity
Unity 6 Cinemachine camera system guide. Use when working with virtual cameras, camera blending, follow cameras, FreeLook, camera shake, or state-driven cameras. Covers Cinemachine 3.x API. Based on Unity 6.3 LTS documentation.
npx claudepluginhub cdata/aria-skills --plugin unityThis skill uses the workspace's default tool permissions.
> Based on Unity 6.3 LTS -- Cinemachine 3.1 package
Implements smooth follow, screen shake, camera zones, and transitions for 2D/3D cameras in Godot 4.3+ with GDScript and C# examples including drag zones and limits.
Unity 6 animation system guide. Use when working with Animator Controllers, animation state machines, blend trees, animation clips, Avatar system, humanoid rigs, root motion, animation events, Timeline, or Cinemachine. Based on Unity 6.3 LTS documentation.
Provides Unity C# scripting patterns covering MonoBehaviour lifecycle, coroutines, async/await, physics APIs, raycasts, collisions, animations, NavMesh, pooling, singletons, ECS, Jobs, and Burst.
Share bugs, ideas, or general feedback.
Based on Unity 6.3 LTS -- Cinemachine 3.1 package IMPORTANT: Cinemachine 3.x renamed CinemachineVirtualCamera to CinemachineCamera
Cinemachine procedurally controls the Unity camera at runtime. Compose camera behaviors from reusable components instead of writing custom camera scripts.
using Unity.Cinemachine; // Cinemachine 3.x (NOT "using Cinemachine;")
CinemachineBrain to Main CameraCinemachineCamerausing UnityEngine;
using Unity.Cinemachine;
public class CameraSetup : MonoBehaviour
{
[SerializeField] Transform playerTransform;
void Start()
{
var vcam = gameObject.AddComponent<CinemachineCamera>();
vcam.Follow = playerTransform;
vcam.LookAt = playerTransform;
vcam.Priority.Value = 10;
}
}
CinemachineCamera + CinemachineFollow. Set Follow target to player.
// CinemachineFollow provides a simple offset-based follow
var follow = gameObject.AddComponent<CinemachineFollow>();
follow.FollowOffset = new Vector3(0f, 5f, -10f);
follow.Damping = new Vector3(1f, 1f, 1f);
CinemachineThirdPersonFollow for collision-aware third-person cameras.
| Property | Description |
|---|---|
ShoulderOffset | Offset from follow target in local space |
CameraDistance | Distance from shoulder point |
CameraSide | 0=left, 0.5=center, 1=right |
CameraRadius | Collision detection radius |
DampingIntoCollision | Damping when moving closer due to collision |
DampingFromCollision | Damping when returning after collision |
CinemachineOrbitalFollow for orbit-around-target cameras controlled by player input. In Cinemachine 3.x, FreeLook is no longer a separate component -- use CinemachineCamera + CinemachineOrbitalFollow + CinemachineInputAxisController.
var orbital = gameObject.AddComponent<CinemachineOrbitalFollow>();
orbital.OrbitStyle = CinemachineOrbitalFollow.OrbitStyles.ThreeRing;
orbital.Radius = 5f;
// Add CinemachineInputAxisController to wire Input System actions
gameObject.AddComponent<CinemachineInputAxisController>();
CinemachinePositionComposer with dead zones and damping for smooth 2D tracking.
var composer = gameObject.AddComponent<CinemachinePositionComposer>();
composer.Damping = new Vector3(1f, 0.5f, 0f);
composer.DeadZoneWidth = 0.1f;
composer.DeadZoneHeight = 0.1f;
composer.ScreenPosition = new Vector2(0.5f, 0.5f);
composer.CameraDistance = 10f; // orthographic distance
Body components control how the camera position follows the target. Add one Body component per CinemachineCamera.
| Component | Use Case |
|---|---|
CinemachineFollow | Simple offset follow with damping |
CinemachineThirdPersonFollow | Collision-aware third-person |
CinemachineOrbitalFollow | Orbit around target (FreeLook style) |
CinemachinePositionComposer | Screen-space framing with dead zones |
CinemachineHardLockToTarget | Snap position exactly to target (no damping) |
CinemachineTrackedDolly | Follow a SplineContainer path |
Moves the camera along a SplineContainer path. Useful for cutscene rails, racing games, or side-scrollers.
var dolly = gameObject.AddComponent<CinemachineTrackedDolly>();
dolly.SplinePath = splineContainer;
dolly.AutoDolly.Enabled = true; // auto-position along spline
dolly.CameraPosition = 0.5f; // 0..1 position on spline
dolly.Damping = new Vector3(1f, 1f, 1f);
Aim components control how the camera rotates toward its LookAt target. Add one Aim component per CinemachineCamera.
| Component | Use Case |
|---|---|
CinemachineRotationComposer | Soft-zone aim with dead zones and damping |
CinemachineHardLookAt | Always face target exactly (no damping) |
CinemachinePanTilt | Manual pan/tilt via input axes (first-person) |
CinemachineGroupFraming | Auto-frame a CinemachineTargetGroup |
For first-person or manual-aim cameras:
var panTilt = gameObject.AddComponent<CinemachinePanTilt>();
panTilt.TiltAxis.Range = new Vector2(-70f, 70f); // clamp vertical look
CinemachineBrain handles smooth transitions automatically.
| Style | Description |
|---|---|
Cut | Instant switch |
EaseInOut | Smooth acceleration/deceleration (most common) |
EaseIn / EaseOut | One-sided easing |
HardIn / HardOut | Hard start or end |
Linear | Constant speed |
Custom | User-defined AnimationCurve |
// Priority-based: Brain blends to highest priority
closeUpCamera.Priority.Value = 20;
wideCamera.Priority.Value = 10;
// Or enable/disable GameObjects -- Brain blends automatically
closeUpCamera.gameObject.SetActive(true);
wideCamera.gameObject.SetActive(false);
Custom per-camera-pair blends use a CinemachineBlenderSettings asset assigned to CinemachineBrain.CustomBlends.
CinemachineStateDrivenCamera maps Animator states to child CinemachineCameras. When the Animator transitions, the corresponding camera activates automatically.
CinemachineStateDrivenCameraCinemachineCamera| Component | Role |
|---|---|
CinemachineImpulseSource | Generates impulse signal at a position |
CinemachineImpulseListener | Receives impulse on a CinemachineCamera |
using UnityEngine;
using Unity.Cinemachine;
public class ExplosionShake : MonoBehaviour
{
[SerializeField] CinemachineImpulseSource impulseSource;
public void Explode()
{
impulseSource.GenerateImpulse(); // default velocity
impulseSource.GenerateImpulse(3f); // scaled intensity
impulseSource.GenerateImpulse(Vector3.up); // directional
}
}
| Property | Description |
|---|---|
Gain | Impulse multiplier (0=ignore, 1=full) |
Use2DDistance | Use 2D distance for falloff |
ChannelMask | Which impulse channels to receive |
CinemachineBasicMultiChannelPerlin adds continuous procedural noise (handheld feel, idle breathing).
| Profile | Use Case |
|---|---|
6D Shake | Full positional + rotational |
Handheld_normal_mild | Subtle handheld |
Handheld_normal_strong | Pronounced handheld |
Frame multiple targets with a single camera.
var group = gameObject.AddComponent<CinemachineTargetGroup>();
group.Targets = new CinemachineTargetGroup.Target[]
{
new() { Object = player.transform, Weight = 1f, Radius = 1f },
new() { Object = enemy.transform, Weight = 0.5f, Radius = 1f }
};
// Add CinemachineGroupFraming to the camera for auto-framing
Cinemachine 3.x uses InputAxis for camera control input. It integrates with Unity's Input System package.
Add this component alongside CinemachineOrbitalFollow or CinemachinePanTilt. It auto-discovers axes on sibling components and connects Input System actions.
using UnityEngine;
using Unity.Cinemachine;
using System.Collections.Generic;
public class CustomCameraInput : MonoBehaviour, IInputAxisOwner
{
[SerializeField] InputAxis horizontalAxis;
[SerializeField] InputAxis verticalAxis;
public void GetInputAxes(List<IInputAxisOwner.AxisDescriptor> axes)
{
axes.Add(new IInputAxisOwner.AxisDescriptor
{
DrivenAxis = () => ref horizontalAxis,
Name = "Horizontal"
});
axes.Add(new IInputAxisOwner.AxisDescriptor
{
DrivenAxis = () => ref verticalAxis,
Name = "Vertical"
});
}
}
var vcam = gameObject.AddComponent<CinemachineCamera>();
vcam.Follow = player; vcam.LookAt = player;
var tpFollow = gameObject.AddComponent<CinemachineThirdPersonFollow>();
tpFollow.ShoulderOffset = new Vector3(0.5f, 0f, 0f);
tpFollow.CameraDistance = 4f;
tpFollow.CameraSide = 1f;
tpFollow.CameraRadius = 0.2f;
var rotComposer = gameObject.AddComponent<CinemachineRotationComposer>();
rotComposer.Damping = new Vector2(0.5f, 0.5f);
using UnityEngine;
using Unity.Cinemachine;
public class CameraTriggerZone : MonoBehaviour
{
[SerializeField] CinemachineCamera zoneCamera;
[SerializeField] int activePriority = 20;
[SerializeField] int inactivePriority = 0;
void Start() => zoneCamera.Priority.Value = inactivePriority;
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
zoneCamera.Priority.Value = activePriority;
}
void OnTriggerExit(Collider other)
{
if (other.CompareTag("Player"))
zoneCamera.Priority.Value = inactivePriority;
}
}
using UnityEngine;
using Unity.Cinemachine;
using System.Collections;
public class CutsceneSequence : MonoBehaviour
{
[SerializeField] CinemachineCamera[] cameras;
[SerializeField] float[] durations;
public IEnumerator PlayCutscene()
{
for (int i = 0; i < cameras.Length; i++)
{
foreach (var cam in cameras) cam.Priority.Value = 0;
cameras[i].Priority.Value = 100;
yield return new WaitForSeconds(durations[i]);
}
}
}
// Each player: separate Camera + CinemachineBrain + CinemachineCamera
// Camera 1: Viewport Rect (0, 0, 0.5, 1) -- left half
// Camera 2: Viewport Rect (0.5, 0, 0.5, 1) -- right half
brain1.ChannelMask = OutputChannels.Channel01;
brain2.ChannelMask = OutputChannels.Channel02;
player1Cam.OutputChannel = OutputChannels.Channel01;
player2Cam.OutputChannel = OutputChannels.Channel02;
[SerializeField] CinemachineImpulseSource impulseSource;
[SerializeField] float shakeForce = 5f;
public void Detonate()
{
impulseSource.GenerateImpulse(shakeForce);
}
| Anti-Pattern | Do This Instead |
|---|---|
Using CinemachineVirtualCamera (v2) | CinemachineCamera |
using Cinemachine; namespace | using Unity.Cinemachine; |
Modifying Camera.main.transform directly | Modify the CinemachineCamera; Brain drives the Camera |
| All cameras at same priority | Give distinct priorities |
| No CinemachineBrain on Main Camera | Always add CinemachineBrain |
Manual Lerp for camera transitions | Use priority switching; Brain handles blending |
CinemachineTransposer (v2) | CinemachineFollow |
CinemachineComposer (v2) | CinemachineRotationComposer |
CinemachineFramingTransposer (v2) | CinemachinePositionComposer |
| Class | Purpose |
|---|---|
CinemachineCamera | Virtual camera (was CinemachineVirtualCamera) |
CinemachineBrain | Drives Unity Camera from active virtual camera |
CinemachineFollow | Offset body (was CinemachineTransposer) |
CinemachineThirdPersonFollow | Collision-aware third-person body |
CinemachineOrbitalFollow | Orbit body for FreeLook |
CinemachinePositionComposer | Screen-space framing (was FramingTransposer) |
CinemachineTrackedDolly | Follow a Spline path |
CinemachineRotationComposer | Soft-zone aim (was CinemachineComposer) |
CinemachineHardLookAt | Snap aim to target |
CinemachinePanTilt | Manual pan/tilt aim |
CinemachineGroupFraming | Auto-frame target group |
CinemachineImpulseSource | Generate camera shake |
CinemachineImpulseListener | Receive shake on camera |
CinemachineBasicMultiChannelPerlin | Continuous procedural noise |
CinemachineStateDrivenCamera | Map Animator states to cameras |
CinemachineTargetGroup | Group multiple targets |
CinemachineBlenderSettings | Custom blend definitions |
CinemachineInputAxisController | Connect Input System to axes |
ICinemachineCamera | Interface for virtual cameras |
| Cinemachine 2.x | Cinemachine 3.x |
|---|---|
CinemachineVirtualCamera | CinemachineCamera |
CinemachineFreeLook | CinemachineCamera + CinemachineOrbitalFollow |
CinemachineTransposer | CinemachineFollow |
CinemachineComposer | CinemachineRotationComposer |
CinemachineFramingTransposer | CinemachinePositionComposer |
CinemachinePOV | CinemachinePanTilt |
CinemachineGroupComposer | CinemachineGroupFraming |
using Cinemachine | using Unity.Cinemachine |
m_Follow / m_LookAt | Follow / LookAt |
m_Priority | Priority.Value |
unity-animationunity-graphicsunity-animation references/timeline.mdunity-input