빠른 흐름
public interface IUpdatable
{
void Tick();
}기본 흐름
분산 Update 호출의 문제
Unity 공식 성능 가이드는 수천 개의 Update 메서드가 쌓일 때 중앙 갱신 관리 구조를 고려하라고 설명합니다. Unity 엔진은 각 MonoBehaviour의 Update를 네이티브와 관리 코드 경계를 넘어 호출하기 때문에, 빈 Update라도 오브젝트 수가 많으면 누적 오버헤드가 생깁니다. 갱신이 실제로 필요한 대상만 중앙에서 순회하도록 구조를 바꾸면 이 비용을 줄일 수 있습니다.
UpdateManager 구현 예제
인터페이스 IUpdatable을 정의하고, 갱신이 필요한 오브젝트를 매니저에 등록해 한 곳에서 순회하는 구조입니다.
public class UpdateManager : MonoBehaviour
{
private readonly List<IUpdatable> items = new();
private void Update()
{
for (int i = 0; i < items.Count; i++)
{
items[i].Tick();
}
}
}갱신이 필요 없어진 오브젝트는 리스트에서 제거하면 되므로, 비활성 상태의 오브젝트에 불필요하게 프레임 비용을 쓰지 않아도 됩니다. 간헐적으로만 갱신해도 되는 시스템은 n프레임마다 한 번만 돌게 만드는 전략과도 잘 맞습니다.
도입 시점과 적합한 상황
Update Manager는 대규모 AI 에이전트, 수백 개의 UI 요소, 환경 오브젝트처럼 갱신 대상 수가 많은 계층에서 특히 효과가 큽니다. 소규모 프로젝트나 오브젝트 수가 적은 상황에서는 오히려 구조가 복잡해지고 의존성이 한 곳에 몰리는 단점이 생길 수 있습니다. 무조건 적용하기보다, 패턴이 반복되고 갱신 대상 수가 체감상 부담이 될 때 도입하는 편이 낫습니다.
체크포인트
| 상황 | 적합한 선택 |
|---|---|
| AI 에이전트·환경 오브젝트가 수백 개 이상 | Update Manager 도입 |
| 비활성 오브젝트에 Update 비용 발생 | 매니저에서 등록·해제로 선택적 순회 |
| 간헐적 갱신으로 충분한 시스템 | n프레임마다 한 번 Tick 호출 |
| 소규모 프로젝트, 오브젝트 수 적음 | 각 MonoBehaviour의 Update 직접 사용 |
| 판단 기준 | Update Manager가 더 맞는 경우 | 그냥 Update가 더 단순한 경우 |
|---|---|---|
| 갱신 대상 수 | 수백~수천 개 이상 | 소수 오브젝트만 갱신 |
| 활성/비활성 제어 | 등록·해제를 명시적으로 관리 가능 | 엔진 수명주기만으로 충분 |
| tick 주기 | n프레임/조건부 갱신이 유리 | 매 프레임 즉시 반응이 필요 |
| 구조 복잡도 | 공통 인터페이스 도입 가치가 큼 | 시스템 규모가 작아 간접화 비용이 더 큼 |
주의할 점
Update Manager 도입 전 실제 병목을 Profiler로 확인하세요. 성능 문제 없이 구조만 복잡해질 수 있습니다.
// ❌ 미리 Update Manager를 도입해 불필요한 복잡도 추가
// 오브젝트 10개짜리 프로젝트에서 등록·해제 코드 관리 부담
// ✅ Profiler에서 Update 비용 확인 후 도입 결정
// Window > Analysis > Profiler > CPU Usage 탭
// "BehaviourUpdate" 항목이 병목인 경우 고려
// ✅ 기본 패턴
public class UpdateManager : MonoBehaviour
{
private readonly List<IUpdatable> items = new();
public void Register(IUpdatable item) => items.Add(item);
public void Unregister(IUpdatable item) => items.Remove(item);
private void Update()
{
for (int i = 0; i < items.Count; i++)
items[i].Tick();
}
}중앙 매니저를 도입한 뒤 등록 해제를 놓치면, 비활성 오브젝트나 이미 파괴된 대상까지 계속 순회하는 버그가 생깁니다. 성능 최적화가 아니라 상태 관리 문제로 번질 수 있습니다.
// ❌ 등록만 하고 제거 안 함
private void OnEnable()
{
updateManager.Register(this);
}
// OnDisable / OnDestroy에서 해제 누락
// ✅ 등록과 해제를 수명주기에 맞춤
private void OnEnable() => updateManager.Register(this);
private void OnDisable() => updateManager.Unregister(this);참고 링크
3 sources