핵심 정리
private static readonly int SpeedId = Animator.StringToHash("Speed");
private static readonly int ColorId = Shader.PropertyToID("_BaseColor");구조 이해
문자열 API의 내부 비용
Unity 공식 성능 가이드는 Animator와 Shader 속성 접근 시 문자열보다 정수 ID를 사용해 비용을 줄이라고 권장합니다. 문자열 버전 API는 내부에서 문자열을 해싱한 뒤 정수 버전으로 전달합니다. 한 번 호출이라면 차이가 미미하지만, Update처럼 매 프레임 호출되는 경로에서는 해싱 비용이 누적됩니다. static readonly 필드로 해시 ID를 미리 계산해 두면 이 비용을 한 번으로 줄일 수 있습니다.
Animator와 Shader에 적용하는 예제
애니메이션 파라미터와 셰이더 속성은 프레임마다 접근되는 경우가 많아 ID 캐싱의 효과가 큽니다. 아래는 점프 트리거를 해시 ID로 발동하는 예입니다.
private static readonly int JumpId = Animator.StringToHash("Jump");
[SerializeField] private Animator animator;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger(JumpId);
}
}셰이더 속성도 마찬가지로 Shader.PropertyToID("_BaseColor")처럼 ID를 미리 캐싱해 두고, material.SetColor(ColorId, value)처럼 정수 버전 API를 씁니다.
유지보수 측면의 장점
성능 외에도 오타 방지라는 유지보수 장점이 있습니다. 파라미터 이름이 여러 곳에 문자열 리터럴로 흩어져 있으면 이름이 바뀔 때 모두 찾아 고쳐야 하고, 오타를 컴파일러가 잡아 주지 않습니다. static readonly 상수로 한 곳에 모아 두면 변경 지점이 하나로 줄고, 잘못 입력해도 IDE에서 추적하기 쉬워집니다.
체크포인트
| 상황 | 적합한 선택 |
|---|---|
| Animator 파라미터를 매 프레임 접근 | Animator.StringToHash로 ID 캐싱 |
| Shader 속성을 매 프레임 변경 | Shader.PropertyToID로 ID 캐싱 |
| 같은 문자열 리터럴이 여러 곳에 산재 | static readonly 상수로 한 곳에 모음 |
| 한 번만 호출되는 초기화 코드 | 문자열 API 그대로 사용해도 무방 |
주의할 점
해시 ID 캐싱은 반복 호출 경로에서만 의미가 있습니다. 초기화 코드처럼 한 번만 실행되는 경우에 강제로 캐싱하면 가독성만 낮아집니다.
// ❌ Update마다 문자열 해싱 — 매 프레임 비용 누적
private void Update()
{
animator.SetFloat("Speed", speed); // 매 프레임 해싱
material.SetColor("_BaseColor", color); // 매 프레임 해싱
}
// ✅ static readonly로 ID 미리 계산 — 해싱 1회로 끝
private static readonly int SpeedId = Animator.StringToHash("Speed");
private static readonly int ColorId = Shader.PropertyToID("_BaseColor");
private void Update()
{
animator.SetFloat(SpeedId, speed);
material.SetColor(ColorId, color);
}참고 링크
3 sources