유니티에서 오브젝트 풀 만들기 Object Pool 2 – 오브젝트 풀 스크립트 만들기
유니티에서 오브젝트 풀 만들기 Object Pool 2 – 오브젝트 풀 스크립트 만들기
오브젝트 풀 시리즈 전체
- 유니티에서 오브젝트 풀 만들기 Object Pool 1 – Pooled Object 정의하기
- 유니티에서 오브젝트 풀 만들기 Object Pool 2 – 오브젝트 풀 스크립트 만들기
- 유니티에서 오브젝트 풀 Object Pool 만들기 3 – 총알 발사하기
오브젝트 풀 만들기
지난 강좌에 이어서 이번에는 PooledObject를 관리하고, 필요한 객체를 요청 받고, 객체를 건내주는 매니저 클래스를 만들어보겠습니다.
매니져 클래스를 구현할 때 접근이 편한 싱글톤으로 구현했습니다. Singleton 제네릭 클래스를 만들고, 이를 상속받아서 구현하는 방식으로 진행합니다. 제네릭 싱글톤 구현에 대한 내용은 여기를 참고하시기 바랍니다.
ObjectPool 스크립트를 만들어 보겠습니다. 유니티에서 Create->C# Script 를 선택해서 스크립트를 새로 생성하고 이름을 ObjectPool로 지정합니다. 스크립트 생성이 완료되면, 아래 내용을 입력합니다.
using UnityEngine; using System.Collections.Generic; public class ObjectPool : Singleton<ObjectPool> { public List<PooledObject> objectPool = new List<PooledObject>(); void Awake() { for (int ix = 0; ix < objectPool.Count; ++ix) { objectPool[ix].Initialize(transform); } } public bool PushToPool(string itemName, GameObject item, Transform parent = null) { } public GameObject PopFromPool(string itemName, Transform parent = null) { } PooledObject GetPoolItem(string itemName) { } }
지난 번과 같은 방식으로 함수를 선언한 뒤에 내용을 하나하나 채워나가겠습니다.
함수 첫 번째 줄에서 지난 강좌에서 만든 PooledObject 클래스를 리스트로 관리하는 변수를 추가합니다. 변수 이름은 objectPool로 지정했습니다.
Awake 함수에서는 오브젝트 풀Object Pool을 초기화 합니다. objectPool 리스트를 루프로 순회하면서 각 PooledObject클래스에 있는 Initialize 함수를 호출해서 초기화를 진행합니다.
이 과정이 진행되면, PooledObject에 지정한 poolCount수 만큼 각 리스트에 객체가 생성되어 추가됩니다.
이제 나머지 함수에 내용을 채워보겠습니다. PushToPool 함수를 아래 내용으로 채워줍니다.
public bool PushToPool(string itemName, GameObject item, Transform parent = null) { PooledObject pool = GetPoolItem(itemName); if (pool == null) { return false; } pool.PushToPool(item, parent == null ? transform : parent); return true; }
PushToPool 함수는 사용한 객체를 ObjectPool에 반환할 때 사용할 함수로, 총 3개의 파라미터를 입력 받습니다. 각 파라미터의 내용은 다음과 같습니다.
- itemName : 반환할 객체의 pool 오브젝트 이름
- item : 반환할 객체 – 게임 오브젝트
- parent : 부모 계층 관계를 설정할 정보
지난 예제와 마찬가지로 사용한 객체를 특정 게임 오브젝트의 자식 게임 오브젝트로 지정하고 싶을 때에만 parent 정보를 전달해주면 됩니다.
먼저 함수의 첫 번째 줄에서 GetPoolItem함수를 호출해서 itemName 파라미터에 전달된 이름과 동일한 pool을 찾습니다. GetPoolItem함수는 ObjectPool스크립트에 추가될 함수로서 아래 부분에 추가됩니다. (궁금하신 분들은 아래 내용을 먼저 확인하셔도 됩니다).
Pool 검색에 실패하면 객체 반환에 실패합니다. 그렇지 않은 경우에는 PooledObject클래스의 PushToPool함수를 호출해서 객체를 poolList리스트에 저장합니다.
객체 반환에 성공했으니, 함수 마지막 부분에서는 true값을 리턴합니다.
이 부분에서 parent == null ? transform : parent 구문이 사용되었는데, 삼항연산자를 이용해서 parent 값이 지정된 경우에는 parent 값을 그대로 사용하고, 지정되지 않은 경우에는 ObjectPool 게임 오브젝트를 parent로 지정하도록 했습니다.
이어서 PopFromPool 함수를 작성해보겠습니다. 아래 스크립트 내용을 PopFromPool 함수에 작성합니다.
public GameObject PopFromPool(string itemName, Transform parent = null) { PooledObject pool = GetPoolItem(itemName); if (pool == null) { return null; } return pool.PopFromPool(parent); }
이 함수는 필요한 객체를 오브젝트 풀에 요청할 때 사용할 함수입니다. 총 두 개의 파라미터를 전달 받고 있습니다. 각 파라미터의 내용은 다음과 같습니다.
- itemName : 요청할 객체의 pool 오브젝트 이름
- parent : 부모 계층 관계를 설정할 정보
이 함수에서 역시, parent 정보는 사용한 객체를 특정 게임 오브젝트의 자식 게임 오브젝트로 지정하고 싶을 때에만 전달합니다.
함수 첫 번째 줄에서 GetPoolItem함수를 호출해서 itemName 파라미터와 이름이 동일한 pool을 찾습니다. 검색에 실패하면 null을 리턴하고 함수를 종료합니다.
검색에 성공한 경우, PooledObject클래스의 PopFromPool함수를 호출해서 오브젝트를 얻고, 이 값을 리턴합니다.
이제 ObjectPool클래스의 마지막 함수인 GetPoolItem함수를 작성하겠습니다. 아래 내용을 GetPoolItem함수에 작성합니다.
PooledObject GetPoolItem(string itemName) { for (int ix = 0; ix < objectPool.Count; ++ix) { if (objectPool[ix].poolItemName.Equals(itemName)) { return objectPool[ix]; } } Debug.LogWarning("There's no matched pool list."); return null; }
이 함수는 전달된 itemName파라미터와 같은 이름을 가진 오브젝트 풀을 검색하고, 검색에 성공하면 그 결과를 리턴합니다.
검색에 실패한 경우에는 null을 리턴하고 경고 메시지를 출력하도록 했습니다.
이제 ObjectPool클래스가 완성되었습니다. 지난 시간에 작성했던 PooledObject클래스를 리스트(배열)로 관리하는 매니저 클래스입니다.
PooledObject를 만드는 부분을 놓치신 분은 여기를 참고하시기 바랍니다.
다음 시간에는 이번에 만든 ObjectPool스크립트를 활용하는 강좌를 진행해보겠습니다.
그 전에 지난 PooledObject클래스를 만든 강좌와 이번 강좌를 한번 복습하시면 전체 내용을 이해하는 데 문제가 없을겁니다.
그리고 강좌에서는 필요한 기능만 구현했기 때문에, 여러분이 필요한 기능을 추가해보시거나 최적화를 진행해 보시는 것도 좋을 것 같네요.
이번 강좌는 여기까지 입니다.
내용 끝까지 읽어주셔서 감사합니다.
배너 클릭은 저에게 많은 힘이 됩니다.
감사합니다 🙂
안녕하세요!! 유니티를 갓 입문한 사람으로써 이해가 쏙쏙 되도록 정리 잘해주셔서 너무 감사하고 힘이 됩니다!
다만 한가지 궁금한 점이
public class ObjectPool : Singleton&It; ObjectPool>
에서 콜론 기준 우측에 있는 게 전부 싱글톤 클래스의 이름이란 얘긴건가요..?
그럼 싱글톤 클래스 스크립트를 짤 때 이름은 저렇게 선언하셨다는 건지 헷갈리네요ㅠㅠ
다시 한번 감사합니다!!
public class ObjectPool : Singleton< ObjectPool >
이게 맞습니다. &It; 이건 잘못들어간 거구요..
오른쪽 내용은 제네릭으로 정의된 싱글톤 클래스를 상속 받겠다는 내용입니다. 그래서 ObjectPool은 싱글톤이 되구요.ㅎㅎ
C# 문법에서 제네릭(Generic)을 살펴보시면 도움이 되실거 같습니다 🙂
아아 그렇군요ㅠㅠㅠㅠ 저도 저런 연산자가 있었나 해서 당황했었거든요ㅠㅠ 정말 많은 도움 되고 있습니다. 이런 식으로 싱글톤 패턴을 이용해서 매니저 클래스를 이용하는 것도, 오브젝트풀을 만드는 법도 로니님(이렇게 부르는 게 맞나요..?) 강좌를 통해 배워갑니다. 언제 완성될지는 모르지만 제 게임이 개발되면 꼭 감사인사라도 드리고 싶습니다!!!
도움이 되셨다니 다행이네요.
네 로니라고 부르시면 됩니다. ㅎㅎ
블로그 자주 들러주세요~ 감사합니다.
넵!! 감사합니다 헤헤
아 그리고 질문 한가지만 더 드려도 될까요ㅠㅠ??
제가 이해하기로는 제네릭 싱글톤 클래스를 따로 만들고, 오브젝트풀 스크립트가 모노비해이비어가 이닌 싱글톤 클래스를 상속받은 것 같은데… 그게 맞다면, 싱글톤 클래스를 스크립트로서 따로 생성해야 하나요? 그러면 싱글톤 클래스의 이름은 어찌 지정해주어야하나요ㅠㅠ 제네릭 싱글톤 패턴을 유니티에 적용시키는 글이 찾아도 로니님 블로그에 밖에 안나와서 아직 이해가 조금 부족한가봅니다ㅠㅠ 공부를 시작한지 얼마 되지 않아 기초가 부족한 점 답답하여도 염치불구하고 답변 부탁드립니다ㅠㅠ
제네릭을 적용한 싱글톤 클래스 선언 내용(본문 내용에 링크 있습니다)을 보면 싱글톤 클래스가 MonoBehaviour를 상속 받고 있기 때문에 이 제네릭 싱글톤을 상속받는 오브젝트 풀 스크립트 역시 MonoBehaviour 입니다. 제네릭 싱글톤 선언하는 부분 글 참고해보세요~
그래도 이해 안되시면 질문 또 주시구요.
안녕하세요. 예제 따라서 하고 있습니다. 그런데 하는 중, transform에 이름이 현재텍스트에 없다는 오류가 뜹니다. 오류코드 cs0103 이구요. 도저히 방법을 찾을 수 없어 문의드립니다.
오류 발생하는 부분을 올려주시면 확인하는데
도움이 될 것 같네요.
정말 많은 도움이 되었습니다
감사합니다( _ _ )
블로그 방문해주셔서 감사합니다.
가끔 들러주시고 배너도 클릭해 주시면 큰 힘이 됩니다 🙂
감사합니다 🙂
안녕하세요 저 역시 위에 제나 님처럼 transform에 이름이 현재 컨텍스트에 없습니다 라는 오류가 뜨고 있습니다. 또한, 혹 스크립트 내의 PooledObject를 Pooledobject로 바꾸어도 무방한가요? PooledObject로 작성 시 오류가 뜨길래 O를 소문자로 바꾸니 오류가 해결 되더라구요.
안녕하세요 저 역시 위에 제나 님처럼 transform에 이름이 현재 컨텍스트에 없다는 오류가 뜹니다. 또한, 혹시 스크립트 작성 시 모든 PooledObject를 Pooledobject로 바꾸어도 무방한가요? PooledObject의 O를 대문자로 작성 시 오류가 뜨는데, 이를 소문자로 바꾸어 작성하면 오류가 해결되더라구요. 너무 궁금한 예제인데 해결이 안되어 문의드립니다 ㅜㅠ
문제가 해결되시면 Pooledobject로 바꾸셔도 됩니다.
제가 예제 코드를 올리다가 오타가 났을 수도 있고 예제를 직접 타이핑 하신거면 거기에서 오타가 났을 수도 있겠네요.
transform 문제는 좀 더 자세히 알려주시면 문제확인하는데 도움이 됩니다.
어느 코드 부분에서 오류가 발생하는지 알려주세요.
감사합니다 🙂
오타가 맞았습니다 ㅜ 무지한 저에게 답장을 달아주시어 감사합니다 ㅜㅠ
블로그 방문 감사합니다 🙂
가끔 들러주시고 배너도 클릭해주세요.
큰 힘이 됩니다 🙂
중간 생략이 너무 많아요..무슨 클래스를 제네릭 싱글톤으로 만든거죠?
오브젝트 풀 스크립트가 상속하는 부분에 보면 Singleton로 돼 있습니다. Singleton 클래스를 제네릭 싱글톤으로 만든거에요.
본문에 “여기”에 링크를 걸어뒀습니다.
다음 링크에서 확인하세요.
https://ronniej.sfuh.tk/unity3d-%EC%A0%9C%EB%84%A4%EB%A6%ADgeneric%EC%9D%84-%EC%A0%81%EC%9A%A9%ED%95%9C-%EC%8B%B1%EA%B8%80%ED%86%A4-%EB%A7%A4%EB%8B%88%EC%A0%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0/
너무 친절하게 설명해주셔서 따라가기 좋네요 감사합니다