Unity / C#
Beginner
Unity 2021.3+ / Unity 6
외부 패키지 없이 구현하는 감쇠 진폭 2D/3D 카메라 셰이크(Camera Shake)
Perlin Noise와 지수 감쇠(Exponential Decay) 공식을 활용해 방향성 반동과 충격 강도를 자연스럽게 표현하는 경량 카메라 흔들림 컨트롤러.
#Unity #C# #Camera #Juice #Game Feel
핵심 개념단순
Random.insideUnitSphere로 카메라를 흔들면 진동이 너무 거칠고 부자연스럽습니다. Mathf.PerlinNoise를 시간 축에 따라 샘플링하고 트라우마(Trauma) 값을 제곱/지수 감쇠시키면 부드러우면서도 강력한 타격감을 전달할 수 있습니다.1. 카메라 셰이크 구현 코드
using UnityEngine;
public class CameraShake : MonoBehaviour
{
public static CameraShake Instance { get; private set; }
[SerializeField] private float frequency = 25f;
[SerializeField] private float maxAngle = 5f;
[SerializeField] private float maxOffset = 0.5f;
[SerializeField] private float decaySpeed = 1.5f;
private float _trauma = 0f;
private Vector3 _originalPos;
private float _timeCounter;
private void Awake()
{
Instance = this;
_originalPos = transform.localPosition;
}
public void Shake(float amount)
{
_trauma = Mathf.Clamp01(_trauma + amount);
}
private void LateUpdate()
{
if (_trauma > 0f)
{
_timeCounter += Time.deltaTime * frequency;
float shakeStrength = _trauma * _trauma; // 비선형 반응 (자연스러운 체감)
float offsetX = (Mathf.PerlinNoise(_timeCounter, 0f) * 2f - 1f) * maxOffset * shakeStrength;
float offsetY = (Mathf.PerlinNoise(0f, _timeCounter) * 2f - 1f) * maxOffset * shakeStrength;
float rotZ = (Mathf.PerlinNoise(_timeCounter, _timeCounter) * 2f - 1f) * maxAngle * shakeStrength;
transform.localPosition = _originalPos + new Vector3(offsetX, offsetY, 0f);
transform.localRotation = Quaternion.Euler(0f, 0f, rotZ);
_trauma = Mathf.MoveTowards(_trauma, 0f, Time.deltaTime * decaySpeed);
}
else
{
transform.localPosition = _originalPos;
transform.localRotation = Quaternion.identity;
}
}
}
2. 파라미터 가이드
| 상황 | 권장 Shake Amount | 체감 효과 |
|---|---|---|
| 경미한 타격 / 권총 발사 | 0.2 ~ 0.3 | 가벼운 찰나의 반동 진동 |
| 근접 피격 / 폭발 주변 | 0.5 ~ 0.7 | 묵직한 화면 흔들림 및 회전 |
| 보스 피격 / 초대형 폭발 | 1.0 | 화면이 강하게 흔들리며 잔상 여운 |