Unity_02 오브젝트, 프리팹, 오브젝트 풀 패턴

SeonggyuMin·2025년 4월 15일

Unity

목록 보기
1/11

1. 오브젝트

1. 게임오브젝트 (GameObject)

씬을 구성하는 오브젝트이며 게임에 존재하는 모든 오브젝트는 게임오브젝트
씬에 존재하여 육안에 보이는 물체 또는 육안으로 보이지 않는 기능을 위한 구성품
게임오브젝트만으로는 독자적인 기능이 없음
실질적인 기능은 컴포넌트들이 수행
게임오브젝트는 컴포넌트들을 가지기 위한 컨테이너

<게임오브젝트 구성요소>

  • name: 게임오브젝트의 이름
  • active: 게임오브젝트의 활성화 여부, 비활성화인 경우 씬에 없는 게임오브젝트로 취급됨
    - activeSelf: 자기 자신 활성화 여부
    - activeInHierarchy: 씬 내에서 이 오브젝트가 실제로 활성 상태인지 여부, 부모 중 하나라도 꺼져 있으면 false가 됨
  • static: 게임오브젝트의 정적상태 여부, 런타임 당시 변경되지 않는 데이터를 지정하여 최적화
  • tag: 게임오브젝트의 태그, 게임오브젝트를 특정하기 위한 수단으로 사용
  • layer: 게임오브젝트의 레이어, 씬에서 게임오브젝트를 분리하는 기준 (카메라의 선별적 표현, 충돌 그룹, 등)
  • component: 게임오브젝트에 포함된 기능 모듈, 실질적인 기능을 수행

2. 자기 자신 참조

자기 자신 게임오브젝트의 기능을 쓰는 경우가 많다. 이 때 사용할 수 있는 방법이 있다.

  1. GameObject gameObject가 이미 프로퍼티로 설정되어 있어 gameObject를 쓰면 됨.
  2. Transform transform도 마찬가지로 transform을 사용하면 바로 자기 자신 오브젝트의 컴포넌트를 사용할 수 있음

Transform은 추가 삭제가 자유로운 다른 컴포넌트와 다르게 게임 오브젝트라면 무조건 가져야 하는 컴포넌트이다. 또한 컴포넌트는 무조건 게임 오브젝트에 붙어있을 수 밖에 없다.

3. 외부 오브젝트 참조

다른 게임오브젝트를 참조하기 위해서는
1. public GameObject target; 선언 후 드래그 앤 드롭 (대문자 GameObject)
2. public GameObject target; 선언 후 target = GameObject.Find("Main Camera") - 이름으로 찾기 (비추천하는 방식, 모든 오브젝트를 탐색하여 참조해야 됨, 오타도 생길 수 있음, 이름이 바뀌기도 함)
3. target = GameObject.FindGameObjectWithTag("MainCamera") 태그로 찾는 방식 - 태그는 미리 캐싱 되어있어 바로 찾을 수 있음, 실수할 가능성도 적음

이 중 세 번째 방법이 가장 권장된다.

4. 외부 컴포넌트 참조

  1. Transform cameraTransform = target.transform;: 타겟의 transform가져오기
  2. Camera cam = target.GetComponent<Camera>();: 타켓의 컴포넌트 가져오기

기타 메서드

  • AddComponent<>(): 컴포넌트 추가하기
  • GetOrAddComponent<>(): 컴포넌트 가져오거나 없으면 추가하고 가져오기
  • Destroy();: 삭제하기
  • Destroy(gameObject);: 게임오브젝트 삭제
  • Destroy(camComponent);: 컴포넌트 삭제

2. 프리팹 (Prefab)

프리팹이란 미리 만들어 놓은 게임오브젝트, 템플릿, 설계도이다. 프리팹 시스템을 이용하여 게임오브젝트를 생성, 설정 및 저장할 수 있으며, 자주 사용하는 게임오브젝트 구성을 복사하여 런타임 시점에 생성하려는 경우 사용한다.

프리팹에셋을 클래스, 프리팹인스턴스를 클래스의 인스턴스로 볼 수 있다.

1. 프리팹 생성 및 사용

  • Hierarchy 창의 오브젝트를 project 창으로 드래그 앤 드롭
  • or project 창에서 Create - Prefab

이후 project창의 프리팹을 Scene 창으로 드래그 앤 드롭으로 배치하여 프리팹 인스턴스를 생성할 수 있다.

2. 프리팹 수정

수정 방법

  • 프리팹 더블클릭
  • or inspector - 프리팹 인스턴스 - OPEN

원본 프리팹 변경 시 인스턴스도 같이 바뀌는 것

  • 프리팹에 컴포넌트 추가 삭제
  • 프리팹의 Material, Sprite, Text 등 속성

원본 프리팹 변경 시 인스턴스는 변경되지 않는 것

  • 프리팹의 Transform
  • 씬 인스턴스에서 수동으로 변경한 값(오버라이드)
    - 수동으로 변경한 값 외의 다른 값들은 여전히 영향을 받음

프리팹 인스턴스 각각 오버라이드 가능

  • 씬 인스턴스에서 프리팹 인스턴스 각각 수정 가능하다.

  • 만약 원복하고 싶다면, inspector - overrides - revert all

  • 반대로 씬 인스턴스 변경점을 프리팹 전체에 적용하고 싶다면 inspector - overrides - apply all

  • 프리팹 해제: Hierarchy - 오브젝트 우클릭 - Unpack Prefab

오버라이딩 된 변경 사항은 속성 왼쪽에 파란색 줄이 있다.

3. 프리팹 런타임 생성

유니티에서 프리팹은 게임오브젝트를 생성하기 위한 설계도 역할을 한다. 런타임 중 프리팹 에셋을 이용하여 프리팹 인스턴스를 생성할 수 있다.

public GameObject gameObjectPrefab;     // 프리팹 참조변수
public Component componentPrefab;       // 프리팹의 컴포넌트 참조변수
	public void Instantiate()
	{
		// Instantiate을 통해 프리팹인스턴스 런타임 생성
		GameObject instance = Instantiate(gameObjectPrefab, Vector3.zero, Quaternion.identity);
		Component component = Instantiate(componentPrefab, Vector3.zero, Quaternion.identity);
	}

3. 생성과 관리

public GameObject go;
go = new GameObject("newGO");

new GameObject를 통해 빈 게임오브젝트를 만들 수 있다. (잘 쓰이지는 않음)

인스턴스 생성 메서드 Instantiate()

public GameObject prefab;

public void Spawn()
{
    Instantiate(prefab);
}

그러나 프리팹을 참조하면 프리팹 인스턴스를 생성할 수 있다. 따라서 생성을 반복하여야 한다면 프리팹으로 만드는 것이 좋다.
Instantiate() 오버로딩

  • Instantiate(GameObject original): 원본 프리팹을 같은 위치에 복제
  • Instantiate(GameObject original, Vector3 position, Quaternion rotation): 위치와 회전을 지정하여 생성
  • Instantiate(GameObject original, Transform parent): 부모를 지정하여 생성
  • Instantiate(GameObject original, Vector3 position, Quaternion rotation, Transform parent): 부모를 지정하여 생성
  • Instantiate<T>(T original):제네릭 버전 (Component나 GameObject 모두 사용 가능)

오브젝트 삭제 메서드 Destroy()

public GameObject target;

public void Despawn()
{
    Destroy(target);
}

Destroy() 오버로딩

  • Destroy(Object obj): 즉시 삭제 (렌더링 끝나고 실제로 사라짐)
  • Destroy(Object obj, float t): t초 후에 삭제됨
  • DestroyImmediate(Object obj): 에디터 전용, 즉시 파괴 (위험함)

가비지 컬렉터

메모리 단편화를 해결하기 위해 가비지 컬렉터가 압축(메모리 주소 당기기)하는 동안 GC spike를 통해 프리징이 발생함.

순환 참조 문제는 구조를 잘 짜면 막을 수 있지만 메모리 단편화는 그렇지 않다. 따라서 다음의 오브젝트 풀 패턴을 통해 어느 정도 방지할 수 있다.

3. 오브젝트 풀 패턴 (Object Pool Pattern)

가비지컬렉터의 메모리단편화를 어느 정도 방지하기 위해 가장 대표적이고 기본적인 최적화 기법 중 오브젝트 풀을 사용할 수 있다.

오브젝트 풀 패턴이란 프로그램 내에서 빈번하게 재활용하는 인스턴스들을 풀(Pool)에 보관한 뒤 인스턴스의 생성&삭제 대신 대여&반납을 사용하는 기법이다.
ex) 빈번하게 생성되는 몬스터, 투사체, UI 등

1. 구현

  1. 인스턴스들을 보관할 풀을 생성
  2. 프로그램의 시작 시 풀에 인스턴스들을 생성하여 보관
  3. 인스턴스 생성이 필요할 때 풀에서 대여하여 사용
  4. 인스턴스 삭제가 필요할 대 풀에 반납하여 보관

2. 장점

  1. 빈번하게 사용하는 인스턴스 생성에 소요되는 오버헤드를 줄임
  2. 빈번하게 사용하느 인스턴스 삭제에 부담되는 가비지 콜렉터의 동작을 줄임

3. 주의점

  1. 미리 생성해놓은 인스턴스들이 사용하지 않는 경우에도 메모리를 차지하고 있음
  2. 오브젝트 풀을 힙 영역의 여유공간이 줄어들어 오히려 프로그램에 부담이 되는 경우가 있음
    1. 필요한 인스턴스 양 보다 약간 여유있는 수를 생성(필요한 수를 너무 초과해서 사용 XX)
    2. 필요한 인스턴스 양 보다 약간 부족한 수를 생성하고 나머지는 생성 및 삭제

0개의 댓글