본문 바로가기
개발/Unity

(Unity) GetComponent 완벽 정리: 기본부터 최적화까지 (feat. InChildren, InParent)

by DinoDev 2025. 12. 26.
728x90
반응형

안녕하세요! 유니티로 게임을 개발하다 보면 가장 많이 치는 코드가 무엇일까요? 아마도 transform.position 다음으로 GetComponent가 아닐까 싶습니다.

"내 오브젝트에 붙은 다른 컴포넌트를 가져오고 싶다!" 혹은 "내 자식 오브젝트의 스크립트를 제어하고 싶다!" 할 때 필수적인 이 함수들.

오늘은 **GetComponent 4대장(기본, InChildren, InParent, plural)**의 정확한 차이점과, 실무에서 꼭 지켜야 할 성능 최적화 꿀팁까지 정리해 보겠습니다.


1. 가장 기본: GetComponent<T>()

가장 흔하게 사용하는 함수입니다. "현재 스크립트가 붙어 있는 바로 그 GameObject" 안에서 컴포넌트를 찾습니다.

  • 탐색 범위: 내 GameObject 하나.
  • 특징: 찾고자 하는 컴포넌트가 없으면 null을 반환합니다.
 
void Start()
{
    // 내 오브젝트에 붙어있는 Rigidbody 가져오기
    Rigidbody rb = GetComponent<Rigidbody>();
    
    if (rb != null)
    {
        rb.AddForce(Vector3.up * 10);
    }
}

2. 자식들 다 나와: GetComponentInChildren<T>()

나(현재 오브젝트)를 포함하여 내 하위(자식, 손자...) 계층 구조를 뒤져서 컴포넌트를 찾습니다.

  • 탐색 범위: 나(Self) + 모든 자식(Children) 오브젝트.
  • 주의점:
    1. 나 자신부터 검사합니다. 내 오브젝트에 해당 컴포넌트가 있다면 자식 껀 무시하고 내 껄 반환합니다.
    2. 깊이 우선 탐색(DFS) 방식으로 찾으며, 하나라도 찾으면 즉시 탐색을 종료하고 반환합니다.
    3. 비활성화(activeSelf == false)된 오브젝트는 기본적으로 무시합니다 (오버로딩으로 포함시킬 수 있음).
 
// 내 자식들(혹은 나) 중에 MeshRenderer가 있으면 하나만 가져와!
MeshRenderer childMesh = GetComponentInChildren<MeshRenderer>();

3. 부모님 계신가요: GetComponentInParent<T>()

이번엔 반대로 위쪽(부모)으로 올라가며 탐색합니다.

  • 탐색 범위: 나(Self) + 부모(Parent) + 부모의 부모...
  • 특징: 역시 나 자신부터 검사합니다. 주로 UI 버튼에서 상위 캔버스의 특정 스크립트를 찾거나, 캐릭터의 파츠(손, 발)에서 몸통(Main Body) 스크립트를 찾을 때 유용합니다.
 
// 내 위쪽 계층에 있는 PlayerController 스크립트 찾기
PlayerController player = GetComponentInParent<PlayerController>();

4. 싹 다 긁어모아: GetComponents<T>() (뒤에 's' 주의!)

위의 함수들은 조건에 맞는 컴포넌트를 '딱 하나'만 찾아옵니다. 하지만 한 오브젝트에 BoxCollider가 3개 붙어있다면요? 혹은 자식들에 있는 모든 Enemy 스크립트를 관리하고 싶다면요?

이때 s가 붙은 함수들을 사용합니다. (GetComponents, GetComponentsInChildren 등)

  • 반환 타입: 해당 컴포넌트들의 **배열(T[])**을 반환합니다.
 
void Start()
{
    // 내 자식들에 있는 모든 'Monster' 스크립트를 가져와서 배열에 담음
    Monster[] monsters = GetComponentsInChildren<Monster>();

    // 반복문으로 전체 제어
    foreach (Monster m in monsters)
    {
        m.Die(); // 전멸 시키기
    }
}

💡 [중요] 실무 개발자의 성능 최적화 Tip

GetComponent 시리즈는 편리하지만, 내부적으로 GameObject를 뒤지는 연산이 들어가기 때문에 비용이 꽤 비싼 함수입니다.

1. 절대 Update() 문에 넣지 마세요!

초보자들이 가장 많이 하는 실수입니다.

// ❌ 최악의 예시 (매 프레임마다 찾으러 다님)
void Update() {
    GetComponent<Rigidbody>().velocity = Vector3.zero;
}

// ✅ 좋은 예시 (캐싱 사용)
Rigidbody rb;

void Start() {
    rb = GetComponent<Rigidbody>(); // 시작할 때 한 번만 찾아서 저장
}

void Update() {
    rb.velocity = Vector3.zero; // 저장된 변수 사용
}

2. TryGetComponent를 애용하세요 (Unity 2019.2+)

최신 유니티 버전에서는 TryGetComponent 사용을 권장합니다. 컴포넌트를 가져오는 동시에 null 체크까지 안전하게 처리하며, 메모리 할당(GC) 측면에서도 미세하게 더 유리합니다.

// 이렇게 쓰세요!
if (TryGetComponent<Rigidbody>(out Rigidbody rb))
{
    // rb가 null이 아닐 때만 실행됨
    rb.mass = 10;
}

마치며

오늘은 유니티 스크립팅의 기초인 GetComponent 패밀리에 대해 알아보았습니다.

  • 내꺼 찾을 땐: GetComponent
  • 자식꺼 찾을 땐: GetComponentInChildren
  • 부모꺼 찾을 땐: GetComponentInParent
  • 여러 개 찾을 땐: GetComponents

이 4가지만 상황에 맞춰 잘 쓰고, 캐싱(Caching)만 습관화한다면 여러분의 코드는 훨씬 깔끔하고 빨라질 것입니다.

728x90
반응형