بنقرة واحدة
tools-unity-cinemachine
// Unity Cinemachine camera system patterns including virtual cameras, blending, and state-driven cameras.
// Unity Cinemachine camera system patterns including virtual cameras, blending, and state-driven cameras.
Mobile-specific Unity optimization patterns for memory, battery, thermal, and performance.
Unity Addressables patterns for asset loading, memory management, reference counting, and remote content delivery.
Unity animation patterns including Animancer, state machines, and performance optimization.
Behavior Designer patterns for AI behavior trees including task creation, shared variables, conditionals, and debugging.
FlowCanvas visual scripting patterns for abilities, custom nodes, and graph execution.
Gameplay Ability System patterns for abilities, effects, attributes, and tags including recursion safety and lifecycle management.
| name | tools-unity-cinemachine |
| description | Unity Cinemachine camera system patterns including virtual cameras, blending, and state-driven cameras. |
Cinemachine is Unity's camera system for dynamic, procedural camera behavior. This skill covers common patterns for gameplay cameras, cutscenes, and camera effects.
using Cinemachine;
public class CameraController : MonoBehaviour
{
[SerializeField] private CinemachineVirtualCamera _mainCamera;
[SerializeField] private Transform _followTarget;
[SerializeField] private Transform _lookAtTarget;
private void Start()
{
_mainCamera.Follow = _followTarget;
_mainCamera.LookAt = _lookAtTarget;
}
public void SetFollowTarget(Transform target)
{
_mainCamera.Follow = target;
}
public void SetLookAtTarget(Transform target)
{
_mainCamera.LookAt = target;
}
}
public class ThirdPersonCameraSetup : MonoBehaviour
{
[SerializeField] private CinemachineVirtualCamera _virtualCamera;
private Cinemachine3rdPersonFollow _bodyComponent;
private CinemachineComposer _aimComponent;
private void Awake()
{
_bodyComponent = _virtualCamera.GetCinemachineComponent<Cinemachine3rdPersonFollow>();
_aimComponent = _virtualCamera.GetCinemachineComponent<CinemachineComposer>();
}
public void SetCameraDistance(float distance)
{
if (_bodyComponent != null)
{
_bodyComponent.CameraDistance = distance;
}
}
public void SetShoulderOffset(Vector3 offset)
{
if (_bodyComponent != null)
{
_bodyComponent.ShoulderOffset = offset;
}
}
public void SetDamping(float damping)
{
if (_bodyComponent != null)
{
_bodyComponent.Damping.x = damping;
_bodyComponent.Damping.y = damping;
_bodyComponent.Damping.z = damping;
}
}
}
public class CameraPriorityManager : MonoBehaviour
{
[SerializeField] private CinemachineVirtualCamera _explorationCamera;
[SerializeField] private CinemachineVirtualCamera _combatCamera;
[SerializeField] private CinemachineVirtualCamera _dialogueCamera;
private const int InactivePriority = 0;
private const int ActivePriority = 10;
private void Start()
{
SetExplorationCamera();
}
public void SetExplorationCamera()
{
_explorationCamera.Priority = ActivePriority;
_combatCamera.Priority = InactivePriority;
_dialogueCamera.Priority = InactivePriority;
}
public void SetCombatCamera()
{
_explorationCamera.Priority = InactivePriority;
_combatCamera.Priority = ActivePriority;
_dialogueCamera.Priority = InactivePriority;
}
public void SetDialogueCamera()
{
_explorationCamera.Priority = InactivePriority;
_combatCamera.Priority = InactivePriority;
_dialogueCamera.Priority = ActivePriority;
}
}
public class CameraBlendController : MonoBehaviour
{
[SerializeField] private CinemachineBrain _brain;
public void SetBlendTime(float duration)
{
_brain.m_DefaultBlend.m_Time = duration;
}
public void SetBlendStyle(CinemachineBlendDefinition.Style style)
{
_brain.m_DefaultBlend.m_Style = style;
}
public void SetInstantBlend()
{
_brain.m_DefaultBlend.m_Style = CinemachineBlendDefinition.Style.Cut;
}
public void SetSmoothBlend(float duration = 1f)
{
_brain.m_DefaultBlend.m_Style = CinemachineBlendDefinition.Style.EaseInOut;
_brain.m_DefaultBlend.m_Time = duration;
}
}
public class StateDrivenCameraController : MonoBehaviour
{
[SerializeField] private CinemachineStateDrivenCamera _stateDrivenCamera;
[SerializeField] private Animator _animator;
private void Start()
{
// Animator is automatically linked via CinemachineStateDrivenCamera inspector
// States are mapped to virtual cameras in the component
}
public void TriggerCameraState(string animatorStateName)
{
// Triggering animator state will automatically switch camera
_animator.CrossFade(animatorStateName, 0.2f);
}
}
public class GameStateCameraManager : MonoBehaviour
{
[SerializeField] private CinemachineVirtualCamera[] _cameras;
private Dictionary<GameState, CinemachineVirtualCamera> _cameraMap;
private void Awake()
{
_cameraMap = new Dictionary<GameState, CinemachineVirtualCamera>
{
{ GameState.Exploration, _cameras[0] },
{ GameState.Combat, _cameras[1] },
{ GameState.Dialogue, _cameras[2] },
{ GameState.Cinematic, _cameras[3] }
};
}
public void OnGameStateChanged(GameState newState)
{
foreach (var cam in _cameras)
{
cam.Priority = 0;
}
if (_cameraMap.TryGetValue(newState, out var activeCamera))
{
activeCamera.Priority = 10;
}
}
}
public class CameraShakeController : MonoBehaviour
{
[SerializeField] private CinemachineImpulseSource _impulseSource;
[SerializeField] private CinemachineImpulseDefinition _lightImpulse;
[SerializeField] private CinemachineImpulseDefinition _heavyImpulse;
public void LightShake()
{
_impulseSource.m_ImpulseDefinition = _lightImpulse;
_impulseSource.GenerateImpulse();
}
public void HeavyShake()
{
_impulseSource.m_ImpulseDefinition = _heavyImpulse;
_impulseSource.GenerateImpulse();
}
public void ShakeWithVelocity(Vector3 velocity)
{
_impulseSource.GenerateImpulse(velocity);
}
public void DirectionalShake(Vector3 direction, float force)
{
_impulseSource.GenerateImpulse(direction.normalized * force);
}
}
public class ContinuousShakeController : MonoBehaviour
{
[SerializeField] private CinemachineVirtualCamera _virtualCamera;
private CinemachineBasicMultiChannelPerlin _noise;
private void Awake()
{
_noise = _virtualCamera.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
}
public void SetShakeIntensity(float amplitude, float frequency)
{
if (_noise != null)
{
_noise.m_AmplitudeGain = amplitude;
_noise.m_FrequencyGain = frequency;
}
}
public void StartCombatShake()
{
SetShakeIntensity(0.5f, 1f);
}
public void StopShake()
{
SetShakeIntensity(0f, 0f);
}
public async UniTask ShakeForDuration(float amplitude, float frequency, float duration)
{
SetShakeIntensity(amplitude, frequency);
await UniTask.Delay(TimeSpan.FromSeconds(duration));
StopShake();
}
}
public class TargetGroupController : MonoBehaviour
{
[SerializeField] private CinemachineTargetGroup _targetGroup;
[SerializeField] private CinemachineVirtualCamera _groupCamera;
public void AddTarget(Transform target, float weight = 1f, float radius = 1f)
{
_targetGroup.AddMember(target, weight, radius);
}
public void RemoveTarget(Transform target)
{
_targetGroup.RemoveMember(target);
}
public void SetTargetWeight(Transform target, float weight)
{
for (int i = 0; i < _targetGroup.m_Targets.Length; i++)
{
if (_targetGroup.m_Targets[i].target == target)
{
_targetGroup.m_Targets[i].weight = weight;
break;
}
}
}
public void ClearAllTargets()
{
while (_targetGroup.m_Targets.Length > 0)
{
_targetGroup.RemoveMember(_targetGroup.m_Targets[0].target);
}
}
}
public class CombatCameraController : MonoBehaviour
{
[SerializeField] private CinemachineTargetGroup _combatGroup;
[SerializeField] private Transform _player;
private readonly List<Transform> _enemies = new();
public void StartCombat()
{
_combatGroup.AddMember(_player, 2f, 2f); // Higher weight for player
}
public void AddEnemy(Transform enemy)
{
_enemies.Add(enemy);
_combatGroup.AddMember(enemy, 1f, 1f);
}
public void RemoveEnemy(Transform enemy)
{
_enemies.Remove(enemy);
_combatGroup.RemoveMember(enemy);
}
public void EndCombat()
{
foreach (var enemy in _enemies)
{
_combatGroup.RemoveMember(enemy);
}
_enemies.Clear();
_combatGroup.RemoveMember(_player);
}
}
public class DynamicFOVController : MonoBehaviour
{
[SerializeField] private CinemachineVirtualCamera _virtualCamera;
[SerializeField] private float _defaultFOV = 60f;
[SerializeField] private float _sprintFOV = 70f;
[SerializeField] private float _aimFOV = 45f;
[SerializeField] private float _fovTransitionSpeed = 5f;
private float _targetFOV;
private void Start()
{
_targetFOV = _defaultFOV;
}
private void Update()
{
_virtualCamera.m_Lens.FieldOfView = Mathf.Lerp(
_virtualCamera.m_Lens.FieldOfView,
_targetFOV,
Time.deltaTime * _fovTransitionSpeed
);
}
public void SetSprintFOV()
{
_targetFOV = _sprintFOV;
}
public void SetAimFOV()
{
_targetFOV = _aimFOV;
}
public void ResetFOV()
{
_targetFOV = _defaultFOV;
}
}
public class DollyCameraController : MonoBehaviour
{
[SerializeField] private CinemachineVirtualCamera _dollyCamera;
[SerializeField] private CinemachineDollyCart _dollyCart;
[SerializeField] private CinemachineSmoothPath _dollyPath;
public void StartDollyShot(float duration)
{
StartCoroutine(PlayDollyShot(duration));
}
private IEnumerator PlayDollyShot(float duration)
{
_dollyCart.m_Position = 0f;
_dollyCamera.Priority = 20;
float elapsed = 0f;
float pathLength = _dollyPath.PathLength;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = elapsed / duration;
_dollyCart.m_Position = t * pathLength;
yield return null;
}
_dollyCamera.Priority = 0;
}
public void SetDollyPosition(float normalizedPosition)
{
_dollyCart.m_Position = normalizedPosition * _dollyPath.PathLength;
}
}
public class CameraConfinerController : MonoBehaviour
{
[SerializeField] private CinemachineConfiner2D _confiner;
public void SetBounds(Collider2D boundsCollider)
{
_confiner.m_BoundingShape2D = boundsCollider;
_confiner.InvalidateCache();
}
public void ClearBounds()
{
_confiner.m_BoundingShape2D = null;
}
public void SetDamping(float damping)
{
_confiner.m_Damping = damping;
}
}
| Issue | Solution |
|---|---|
| Camera not switching | Check priorities |
| Jerky movement | Adjust damping values |
| Shake too intense | Lower amplitude gain |
| Wrong blend | Check custom blends in brain |
| Target lost | Verify Follow/LookAt assigned |
| Confiner issues | Call InvalidateCache() |