유니티 프로그래밍 기초 : 프리팹(Prefab)-1

프리팹은 게임 오브젝트와 그에 속해있는 컴퍼넌트의 정보를 저장한 템플릿형태의 에셋파일입니다. 템플릿형태이기 때문에 같은 형태의 오브젝트를 여러번 반복해서 생성해야될 때 유용하게 사용됩니다.

간단하게 말하면 붕어빵 틀을 만든다고 생각하면 됩니다.

붕어빵을 손수 만들면 한두개야 정성스럽게 손으로 모양 잡아가면서 만들수야 있겠지만 그걸 수십, 수백개를 만들어야되면 매우 비효율적이게 되어 붕어빵 틀을 통해 붕어 모양으로 붕어빵을 손쉽게 만들 수 있습니다.

붕어빵을 일일이 만드는게 게임 오브젝트를 일일이 만드는 것이었다면 붕어빵 틀을 만드는건 프리팹을 만들어서 같은 성질의 게임 오브젝트를 원하는만큼 만드는 것이라고 보면됩니다.

붕어빵 틀에 앙꼬로 팥이나 슈크림중 아무거나 골라넣어도 붕어빵이 만들어지는 것처럼 성질내에서 변형을 줘서 각기 다른방식으로도 게임오브젝트를 생성해낼 수 있습니다.(적이라는 프리팹이면 HP, 공격력 등등)

 

1. 장점

재사용이 용이 : 같은 특징을 가진 게임 오브젝트를 반복생성하기 좋습니다. 비행기 게임에서의 비행기 미사일이라던가 스테이지를 가리지 않고 자주 만나는 잡몹수준의 적 등을 반복적으로 생성하기 좋습니다.

유지보수 : 프리팹에는 컴퍼넌트가 있고(스크립트도 컴퍼넌트에 포함됨) 프리팹끼리 모두 공유되기 때문에 수정하기 용이합니다. 밸런스 패치라던지 기능추가시 일괄 적용이 됩니다.

 

2. 단점

생명주기를 확실하게 해야함 : 이것은 단점이라기보단 프리팹 사용시 주의해야할 부분으로 프리팹뿐 아니라 게임 오브젝트도 사용하지 않는 것들은 Destroy로 제거하지 않는 경우 메모리를 지속적으로 차지하게 됩니다.

예를 들어 비행기 게임에서 미사일을 쏴서 적을 맞추지 못해서 화면 밖으로 나갔는데 그 미사일을 Destroy해주지 않으면 실제로는 쓰이지 않지만 화면밖에서 계속 미사일이 이동하는 상태가 되며 계속 메모리를 차지하게 됩니다. 이것이 누적되면 문제가 발생합니다.(팅긴다던지 다운먹는다던지 블루스크린이라던지)

 

3. 예문

일단 프리팹을 만들고자 하는 게임 오브젝트를 선택합니다.

 

프리팹으로 만들고자 하는 게임 오브젝트를 에셋쪽으로 드래그하면 해당 게임 오브젝트의 프리팹이 생성됩니다.

여기서 생성된 Box라는 프리팹은 이전 AddForce를 통한 이동구현에서 방향키를 통해 움직이던 Box 게임 오브젝트입니다.

이제 하이어라키에 있는 Box라는 게임 오브젝트를 삭제하고 대신 Box 게임 오브젝트의 프리팹을 대량생성해보겠습니다.

일단 하이어라키에서 우클릭후 Create Empty를 해서 텅 비어있는 게임 오브젝트를 생성합니다. 게임에서 보이진 않지만 스크립트를 실행하기 위해 스크립트 컴퍼넌트를 달아줄 게임 오브젝트로 사용합니다.

 

CreateEmpty를 통해 PrefabSpawner라는 텅빈 오브젝트가 생성됩니다. 이 오브젝트는 위치값인 Transform만을 가집니다.

 

이 PrefabSpawner라는 게임 오브젝트에 Box 프리팹을 생성하는 스크립트를 넣어주기 위해 스크립트 PrefabSpawn을 작성합니다.

 

 

 

이렇게 작성한후 이 스크립트를 빈오브젝트인 PrefabSpawner에 드래그해서 넣어줍니다.

이 스크립트는 GameObject boxPrefab이라는 변수에 들어간 게임 오브젝트를 스페이스키를 누를때마다 좌표0,0,0에 회전값 기본으로 생성합니다.

아직까지는 boxPrefab에 값이 없는 Null 상태이기에 스페이스키를 눌러도 Null 오류만 나올뿐 아무런 반응이 없습니다.

boxPrefab에 위에서 드래그해서 만든 Box오브젝트의 프리팹 값을 넣어주면 정상적으로 생성이 됩니다.

그러기 위해서 값을 넣는방법으로는 public으로 선언해서 인스펙터에서 드래그해서 넣는 방법이 있고 private면 Start()안에서 해당 프리팹의 경로를 직접 지정해주면 됩니다.

 

 

PrefabSpawner(Empty Object로 만들었던 빈 오브젝트)에 있는

PrefabSpawn 스크립트의 boxPrefab(public GameObject 변수)에

위에서 드래그해서 만든 Box 프리팹을 드래그해서 넣어줍니다.

만약 private라서 직접 경로를 넣고 싶은 경우 다음과 같이 만듭니다.(private라도 SerializeField를 사용시 public처럼 인스펙터에서 드래그해서 넣어주면 됩니다.)

 

 

private시 인스펙터에서 접근할 수 없기 때문에 Start()에서 직접적으로 프리팹의 경로를 설정해줍니다. 기본적으로 프로젝트 생성시 Assets폴더에 Scenes라는 빈폴더와 main.scene 하나가 있는 상태로 경로의 시작은 Assets부터 시작하게 됩니다. 이후 자신이 파일정리한대로 경로를 이어나가면 됩니다.

 

이렇게 CreateEmpty로 PrefabSpawner라는 게임 오브젝트를 만들고

그 안에 PrefabSpawn스크립트를 컴퍼넌트로 넣은후

PrefabSpawn스크립트에 Null이었던 boxPrefab에 만들어낸 box프리팹을 넣어주면 됩니다.(인스펙터에서 드래그를 하던 프리팹 경로를 지정해주던)

이렇게 하면 box프리팹을 PrefabSpawn스크립트로 생성하는걸 담당하는 눈에 보이지 않는 오브젝트 PrefabSpawner가 완성됩니다.

실행시 다음과 같이 나옵니다.

 

 

스페이스 키를 누를때마다 box프리팹이 생성됩니다. 물리엔진이 적용되는 상태에서 같은 위치에서 프리팹들이 생성되다보니 서로를 튕겨내고 있습니다. 그리고 box프리팹은 이전 포스팅인 AddForce로 이동하는 스크립트를 담고 있기 때문에 무수히 생성되는 프리팹들은 전부 방향키나 WASD조작에 반응하여 움직입니다.

그리고 영상을 보면 프리팹이 무수히 나오는데 눈에 보이지 않는 위치에 가서 실질적으로 사용되지 않음에도 제거되지 않았기 때문에 메모리를 계속 차지하게 됩니다. 물론 저 화면밖으로 멀리보낸 오브젝트를 다시 조작해서 화면 안으로 다시 가져올 수 있습니다.

이것을 Destroy를 하지 않으면 메모리를 계속 차지하게 되고 새로운 프리팹들도 메모리를 차지하기에 컴퓨터의 한계를 넘어서면 오류가 발생합니다. 그래서 실질적으로 사용하지 않는 시점에서 Destroy를 통해 제거를 해줘야 합니다.

예를 들면 슈팅게임에서는 미사일을 발사할때 미사일 프리팹이 생성되고 그 미사일이 상대를 맞추거나 화면 밖으로 나가면 Destroy로 제거하는식입니다. 적의 경우도 마찬가지로 비행기 게임에서 잡몹을 제거하지 못하고 이들이 맵밖으로 이탈하면 Bomb같이 맵 전체 광역기에 한해서는 공격이 가능하다보니(게임 룰마다 다름) Bomb가 닿는위치까지는 남겨두지만 그 이상 멀어지면 Destroy로 제거해버립니다.

 

이번 포스팅은 일단 프리팹의 생성만을 중점으로 두고 만들었기 때문에 오브젝트끼리 겹쳐서 서로 튕겨내는 현상이(일반적인 게임에서는 버그) 일어나는 상황이고 같은 오브젝트만을 생성하였는데 다음 포스팅은 프리팹의 속성을 변경하여 크기라던지 색상이라던지 아니면 스크립트의 변수값 등을 변경하는 것을 다루도록 하겠습니다.

 

이상으로 이번 포스팅을 마치겠습니다.

댓글 남기기