Quick Reference
Instantiate는 prefab 또는 object를 clone하고, Destroy는 GameObject·Component·asset 중 넘긴 대상만 제거합니다. 생성하는 코드가 반드시 owner를 가져야 하며, owner가 destroy할지 pool에 return할지 한 가지 정책으로 정합니다.
| 작업 | API | 결과 | 확인할 점 |
|---|---|---|---|
| 생성과 world pose | Instantiate(prefab, pos, rot) | root object clone | scene·parent 소유권 |
| 생성과 hierarchy | Instantiate(prefab, parent) | parent 기준 배치 | local/world pose 정책 |
| Component만 제거 | Destroy(component) | 그 Component만 제거 | GameObject는 남음 |
| object 전체 제거 | Destroy(gameObject) | children·components도 제거 | 다른 reference는 null-like 상태 |
| 지연 제거 | Destroy(obj, delay) | scaled time 뒤 예약 파괴 | timeScale=0이면 delay 진행 안 함 |
생성과 parent
생성과 parent 지정은 별개 결정입니다. world spawn position이 기준이면 position·rotation overload를 쓰고, socket 아래 local offset이 기준이면 parent를 지정한 다음 local transform을 명시합니다. 부모를 firePoint의 parent로 잘못 넘기면 muzzle 위치가 아니라 다른 hierarchy 기준에 생성될 수 있습니다.
[SerializeField] private Bullet bulletPrefab;
[SerializeField] private Transform firePoint;
public Bullet SpawnBullet()
{
Bullet bullet = Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
bullet.Launch(firePoint.forward);
return bullet;
}Instantiate가 prefab의 [SerializeField] reference와 Component state까지 복제한다는 점도 고려합니다. runtime-specific target, owner, cancellation token처럼 prefab에 남겨서는 안 되는 값은 spawn 직후 명시적으로 주입합니다.
Destroy 예약과 ownership
Destroy는 호출 순간 C# reference를 즉시 지우는 방식이 아닙니다. 실제 제거는 현재 Update loop 뒤, rendering 전까지 예약됩니다. delay를 준 경우 timer는 호출 시점부터 시작하고 scaled time 영향을 받습니다. pause에서 수명 종료가 계속되어야 하면 Destroy(obj, seconds) 대신 unscaled timer를 가진 owner가 종료 시점을 결정합니다.
public void Despawn(Bullet bullet)
{
// 이 prefab이 pool 소유라면 Destroy와 섞지 않습니다.
bullet.ReleaseOnce();
}Component를 파괴하면 sibling Component와 GameObject는 계속 남습니다. GameObject를 파괴하면 Transform children과 모든 Component가 같이 사라집니다. DestroyImmediate는 Editor tooling 등 명확한 경우를 제외하면 runtime gameplay에서 사용하지 않습니다.
pool 선택
짧은 object가 반복 생성된다는 사실만으로 pool이 정답은 아닙니다. spawn frequency, instantiate cost, peak concurrent count, reset complexity를 profile로 확인합니다. pool로 전환하면 Destroy가 아니라 Release가 종료 API가 되고, event·coroutine·physics·VFX state reset과 double return 방지가 새로운 책임이 됩니다.
자주 틀리는 부분
| 증상 | 원인 | 수정 |
|---|---|---|
| 생성 위치가 socket과 다름 | parent/local/world 기준 혼동 | spawn pose와 parent policy를 코드에 명시 |
| pause 중 delayed destroy가 멈춤 | Destroy delay가 timeScale 영향을 받음 | unscaled timeout owner 사용 |
| destroy 뒤 reference를 계속 사용 | actual destruction이 예약됨 | 종료 상태 flag와 reference clear 정책 적용 |
| pool object를 Destroy | pool이 다시 그 instance를 대여하려 함 | 소유자별 Destroy 또는 Release 하나만 사용 |
| Component만 지워야 하는데 GameObject 제거 | Destroy 대상 범위 혼동 | Component/GameObject를 명시적으로 전달 |
참고 링크
2 sources