본문 바로가기
[ Unity ]/- 유니티 실습

유니티 2장(오브젝트 풀링, 리스트, 배열, 프리펩, 오브젝트 충돌)

by MRG 2020. 8. 4.
728x90
반응형
728x90

▣ 안녕하세요 ^^
이번장은 오브젝트 풀링을 공부해 보겠습니다.
오브젝트 풀링이 무엇인지 함께 실습으로 공부하면서 진행하겠습니다.


▣ 그리고 다시 말씀드리지만 제가 드리는 방법은 정답이 아닌 
여러 방법 중에 한 가지임을 명심하시고
저와 함께 유니티를 공부한다고 생각해주시면 감사하겠습니다. 

 

▣ 먼저 3D로 프로젝트를 생성해주시고 
3D 게임 오브젝트 캡슐과 바닥을 생성해줍니다.
저는 캡슐을 bullet이라고 이름을 지었습니다. 
계속 총알이 떨어지는 게임을 만들 겁니다. 

 

▣ 그런 다음에 bullet오브젝트에 Rigidbody를 추가해 줍니다. 

 

▣ 그리고 게임을 플레이해보면
기본적으로 3D오브젝트에 추가된 Collider까지 캡슐이 떨어지는 걸 확인할 수 있습니다. 
Rigidbody를 보면 Use Gravity라는 목록이 있는데
이건 기본적으로 유니티에서 Y값을 중력으로 - 해주신다고 생각하시면 됩니다.
우리가 직접 스크립트에서 y를 계속 -- 하는 것과 같다고 생각해 주세요.
이제 떨어지는건 다 되었습니다.

 

▣ 그리고 이번에는 스크립트를 추가해서 총알이 바닥에 닿으면 사라지게 해 보겠습니다.

 

▣ 이렇게 스크립트를 드래그 해서 넣거나 직접 컴포넌트에서 입력을 해서 추가를 하셔도 됩니다.
저는 스크립트를 항상 컴포넌트 위에 넣습니다. 
혹시 우리가 작업을 하다가 public으로 다른 오브젝트를 추가할 일이 있을 수 있기 때문에 이렇게 해두었습니다.

 

▣ 그리고 바닥에 이름을 Ground로 변경해 주고 
Tag를 추가해주겠습니다. 
이건 제가 총알이 어디에 닿을지를 오브젝트 이름이 아닌 tag로 구분하기 위해서입니다. 

 

▣ 바닥에 tag를 Ground로 구분해 주겠습니다.
그리고 이건 나중에 바닥을 구분할 때 잘 생각해서 이름을 정해야 합니다.
이건 나중에 플레이어 발소리를 내는 코딩을 할 때 다시 이야기하도록 하겠습니다. 

 

▣ 그리고 Ground오브젝트에 tag를 Ground로 변경해 주겠습니다. 

 

▣ bullet 스크립트로 들어가서 OncollsionEnter함수를 추가해주겠습니다. 
OncollsionEnter는 rigidbody 충돌 영역에 딱 닿을 때 collsion 매개변수에 값이 전달됩니다. 
쉽게 그 함수가 작동합니다.
그래서 collsion에 쌓인 게임 오브젝트에 태그가 Ground이면 
현재 게임 오브젝트를 삭제해라라고 코딩했습니다. 
그리고 저장을 합니다. 

 

▣ 게임 뷰에서 플레이를 해서 확인을 하면 
총알이 바닥에 닿으면 오브젝트 자체가 삭제되는 걸 확인할 수 있습니다. 
이렇게 코딩을 하고 프리 펩을 만들어서
계속 떨어지게 만들고 삭제하고 생성을 반복하면
컴퓨터가 무리하게 됩니다.
컴퓨터가 삭제하고 생성하는 건 많은 메모리를 요구하기 때문입니다.
그래서 최적화에 좋지 못합니다.
그래서 보통은 비활성화로 코딩을 하게 됩니다. 

 

▣ 이렇게 말이죠 이건 단순히 
우리 눈에만 안 보일뿐 오브젝트를 끄게만 코딩을 했습니다.

 

▣ 그리고 다시 게임 뷰에서 플레이를 해서 확인해보면
총알 오브젝트는 남아있고 비활성화만 된 걸 확인할 수 있습니다.
그럼 이제 이렇게 생각해 볼 수 있습니다.
이렇게 해서 프리 펩으로 총알을 여러 개를 만들면 어떻게 될까요?
네 이것도 최적화에 좋지 못합니다.
우리 눈에는 안 보이지만 계속 생성하고 비활성화를 하게 되면 
그 자리에 계속 남아있기 때문에 
메모리에 쌓이게 됩니다. 
그럼 최적화 게 안 좋겠죠?
그래서 딱 사용할 오브젝트 수를 정해서 그것만 돌려서 사용합니다.
그걸 오브젝트 풀링이라고 합니다. 
그럼 이제부터 하나하나 만들어보겠습니다. 

 


▣ 먼저 2D 이렇게 총알에 위치가 보이게 전환을 해주세요.
왜 이렇게 하냐면 총일이 떨어지는 구역을 정해주기 위해서입니다. 

 

▣ 그리고 총알이 떨어지는 위치에 총알들을 복제해서 각각 배치합니다. 
이렇게 해서 플레이를 해보면 내가 원하는 위치에 잘 떨어지는 걸 확인할 수 있습니다.
하지만 똑같은 속도와 시간으로 떨어져서 별로 원하는 코딩이 아닌 거 같습니다. 
다시 수정해보죠

 

▣ 먼저 총알을 생성하고 관리하는 총알 매니저를 생성하겠습니다.
bulletManager는 형체가 필요 없어서 빈 오브젝트를 생성했지만 어디에 있는지 모르겠습니다.
그럴 때에는 컴포넌트에서 BulletManager이름 왼쪽에 상자를 누르면 이렇게 모양으로 
표시하는 메뉴가 나오게 됩니다.
이걸 사용하시면 됩니다.

 

▣ 그리고 총알을 프리 펩으로 만들겠습니다.
간단합니다. 총알 오브젝트를 에셋에 드래그 하면 끝입니다. 

 

▣ 그리고 아까 만들었던 총알들은 모두 삭제하고 
BulletPoint를 생성해 줍니다. 
이건 3D 큐브로 만들었습니다.

 

▣ 이렇게 3개를 만들었습니다.
이건 총알이 떨어질 위치들을 의미합니다. 
랜덤에 시간으로 생성하고 랜덤에 위치로 배치해서 떨어드릴 예정입니다.

 

▣ 총알을 관리해 줄 bulletManager스크립트를 만들고 아까 만들었던 
bulletManager에 넣습니다. 

 

▣ 그리고 이렇게 총알을 생성할 프리 펩과 총알을 관리할 리스트 
그리고 총알 생성 포인터를 관리할 배열을 만들었습니다. 
public은 모든 곳에 공유하는 걸 의미합니다.
저장을 하고

▣ BulletManager를 보면 이렇게 BulletManager스크립트에 BulletPoints라는 배열이 공유된 걸 확인할 수 있습니다.
여기에 우리가 BulletPoint를 넣을 건데 하나하나 넣으면 불편하니 우선

▣ BulletManager를 그림처럼 잠그겠습니다.
그럼 다른 오브젝트를 눌러도 다른 오브젝트 컴포넌트 정보로 넘어가지 않습니다. 
이때

 

▣ 포인트 3개 오브젝트를 한꺼번에 드래그 해서 
BulletPoints배열에 넣어주면

 

▣ 이렇게 Points3개가 넣어진 걸 확인할 수 있습니다.
잠금을 다시 해제하고

 

▣ BulletPoint에 있는 BoxCollider를 Remove 해줍니다.
BulletPoint는 충돌 없이 그냥 위치이기 때문에 삭제해 주고
다시 스크립트로 넘어갑니다.

 

 

▣ 그런 다음에 경과시간 변수와 생성할 bulletCount를 변수로 선언합니다.
그리고 Start함수에서 10개를 생성하는 코드를 for문으로 코드 했습니다.
프리 펩을 public으로 수정하는지 잊지 마세요.
그리고 Instantiate로 생성을 하고 
리스트에 bullet를 넣습니다.
그리고 처음에는 총알이 나와야 하지 않기 때문에 비활성화를 해주었습니다. 

 

 

▣ 1초에 60 프레임으로 작동하는 Update함수에서 경과시간에 값을 넣고
랜덤 시간과 랜덤 위치에 대한 지역변수를 선언 및 정의를 해줍니다.
그리고 경과시간이 되면 
bulletList에 제일 처음 리스트를 활성해 주고 
그 위치를 아까 우리가 만들었던 포인트 요소에 랜덤 값으로 넣습니다.
그럼 랜덤 위치로 위치하겠죠?
그리고 다시 시간을 초기화해 줍니다. 

 

▣ 그리고 확인했는데 먼가 이상합니다.
총알들끼리 서로 충돌해서 이상하게 나옵니다.
그럼 이제 서로 충돌하지 않게 변경해 보겠습니다. 
Bullet프리 펩을 선택하고 Layer메뉴를 추가하겠습니다.

 

▣ Bullet이라고 추가를 하고

 

▣ 에디터 메뉴에서 Project Settings를 눌러줍니다. 

 

▣ 그리고 Physics에서 bullet항목에서 bullet끼리 충돌하지 않게 
체크를 지워줍니다. 
그리고 확인을 해보면 총알끼리 서로 충돌하지 않는 걸 확인할 수 있습니다.
그런데 여기서 또 문제가 있습니다. 
총알에 리스트가 다음으로 넘어가지 않는 걸 확인할 수 있습니다.
이건 리스트에 0번이 동일하기 때문에 
계속 같은 리스트만 활성화 비활성화를 진행하고 있는 겁니다.
그럴 때에는 총알이 바닥에 닿으면 
비활성화되는 부분에서 충돌한 오브젝트를 리스트에 추가하면 됩니다.
그럼 0번째 리스트가 비활성화되고 맨뒤에서 리스트로 추가되면 
모든 오브젝트를 돌려서 사용하게 됩니다.
이건 직접 실습하면서 보겠습니다. 

 

▣ 총알에 리스트를 스크립트 오브젝트마다 클래스를 공유하기 위해 static 영역으로 
설정했습니다. 이건 데이터 영역으로 보내서 
서로 공유한다고 생각하시면 됩니다.
이 부분은 제가 C언어 장에서 한번 공부하시면 이해가 되실 겁니다. 

 

▣ 그리고 업데이트 함수에서 생성되고 떨어진 총알을 리스트 목록에서 
삭제되는 코드를 추가해 줍니다.
그럼 계속 같은 0번째만 사용하지 않고 
다음 0번째 리스트를 사용하게 됩니다. 

 

▣ bullet스크립트로 들어가서 BulletManager.bulletList.Add로 
바닥에 닿은 현재 오브젝트를 추가하면 됩니다.
Add는 리스트 맨뒤에 추가를 해줍니다.
그럼 맨 처음에 떨어진 오브젝트가 맨뒤에 리스트에 추가돼서 
계속 돌려서 사용하게 됩니다. 

 

▣ 직접 확인을 해보면 하나하나 돌려서 사용하는 걸 확인할 수 있습니다.
이건 몬스터나 아이템에도 적용해도 됩니다. 


▣ 자 오늘은 이렇게 오브젝트 풀링에 대해 공부해 보았습니다.
조금 어려운 내용도 있었지만,
간단하게 이해하면 삭제하고 다시 생성하는 건 최적화에 좋지 못해서
오브젝트를 딱 정해서 생성하고 그걸 돌려쓰는 게 오브젝트 풀링이다라고 생각해 주세요.
제가 말씀드린 방법이 정답은 아니니 이점 참고해 주시고요.
하시다가 궁금하신 사항 있으시면 댓글 남겨주세요.
그럼 다음장에서 뵙겠습니다.


▣ 포기하지 마세요!!! 저도 했습니다!!! 파이팅!!!

728x90
반응형

댓글