이전 글

간단프레임워크 (1) - 오브젝트풀

-----------------------------------------


게임 개발하면서 사운드, 이펙트, 이미지, 텍스트 등 여러가지 리소스 관리할 일이 많은데, 이런 리소스 관리를 간단하게 할 수 있는 스크립트들을 만들어봤음. 

원래 예전에는 Resources 폴더에 다 두고 CSV파일 등을 통해 파싱해서 리소스매니저를 쓰곤 했는데 매번 데이터 파일 고치기도 귀찮고… 그렇다고 리소스매니저 없이 사용하는 측 인스펙터에 그때그때 넣어주자니 뭐 수정 할 때 마다 어디서 썼는지 찾아가면서 수정하기도 귀찮고…

마침 이번에 애셋 할인하는 김에 OdinInspector를 구매했는데, Dictionary 를 Serialize 하는 기능이 있다고 해서 이 기능을 이용해서 리소스 매니저를 만들어 봤음.


아래 코드들은 OdinInspector랑 DOTween (사운드매니저용) 있어야 돌아가니 감안하고 보자.


ResourceDataBase.cs


viewimage.php?id=2abcdd23dad63db0&no=24b0d769e1d32ca73cec81fa11d02831ce3cef1b9542c00ceb084620f9a3823a446e629c8148f2cd474db838d40bd2198bb7c35981296906ad48cb7195f505b550b22d


먼저 리소스데이터의 부모클래스. 관리할 리소스들을 제너릭으로 해뒀고 단순히 Dictionary를 들고 있는 ScriptableObject 임. 이걸 필요한 리소스마다 상속받아서 아래와 같이 사용함.


viewimage.php?id=2abcdd23dad63db0&no=24b0d769e1d32ca73cec81fa11d02831ce3cef1b9542c00ceb084620f9a3823a446e629c8148f2cd474db838d40bd2198bb7c35981296956f91cc472c6aa51b5b2ccc1

보면 알겠지만 구현부가 텅텅빈 단순히 Generic 상속 클래스랑 ScriptableObject를 만들어 줄 수 있는 메뉴 Attribute만 붙어있는 클래스들임. Prefab ,AudioClip, Texture, Particle 등 필요한 타입으로 만들어다가 쓰면 됨. 나 같은 경우엔 주로 Prefab, AudioClip, EffectPrefab 으로 사용하고, 혹시몰라서 Sprite, Texture2D, Text 등도 만들어 두긴 함.


이렇게되면 애셋메뉴에서 이런식으로 각 DB들을 만들 수 있고, 각 DB들은 리소스의 ID값과 리소스를 지니게 됨.

viewimage.php?id=2abcdd23dad63db0&no=24b0d769e1d32ca73cec81fa11d02831ce3cef1b9542c00ceb084620f9a3823a446e629c8148f2cd474db855b808d11e99b2cec9f6145454c2364c06cd76ad781e4e31ca


viewimage.php?id=2abcdd23dad63db0&no=24b0d769e1d32ca73cec81fa11d02831ce3cef1b9542c00ceb084620f9a3823a446e629c8148f2cd474db855b808d11e99b2cec9f614545496631c559d73f6789451878d

실제 사용하는 쪽에선

[SerializeField]

AudioClipResourceDB audioClipDB;

와 같이 각 Resource DB를 선언한 후 만들어 둔 ScriptableObject를 로드해다가

audioClipDB.GetItem(id);

처럼 아이템을 받아올 수 있음.


ID는 각 매니저쪽에서 상수나 Enum같은걸로 관리하면 코드짤 땐 더 편할듯?? 아예 Dictionary Key를 enum으로 지정해도 되긴 한데.. 이러면 리소스추가할때마다 enum 수정해야해서 귀찮으니 장단점 따져봐야 할듯.



이 기능들을 이용해서 실제로 가장 많이 쓰이게 될 EffectManager랑 SoundManager를 만들었음.


먼저 EffectManager.cs

viewimage.php?id=2abcdd23dad63db0&no=24b0d769e1d32ca73cec81fa11d02831ce3cef1b9542c00ceb084620f9a3823a446e629c8148f2cd474db838d40bd2198bb7c35981296955fc1f992594a052b5883769


이펙트 매니저의 경우 ParticleSystem으로 ObjectPool을 만들어서 쓸까 하다가.. 경험상 파티클을 쓰지 않는 이펙트들도 종종 있던 터라 그냥 Prefab기반의 풀링을 이용하기로 하고 ObjectPoolManager를 그대로 사용함.


주요 기능은 당연히 Effect Play하는 부분인데.. PlayOneShot이랑 PlayTimer 로 나눠놨음.

PlayOneShot은 말그대로 Looping 없는 이펙트를 한번만 실행한 후 다시 돌려놓는 기능이고, PlayTimer는 루핑이 있거나, 게임오브젝트 기반 이펙트를 생성한 후 특정 time 후에 제거하는 기능임. 루핑관련으로 사용한다면 예를들면 드래곤이 브레스를 3~5초간 발사한 후 제거해야한다던가..? 로 생각해봤음.


실제 구현하는 과정에선 생각없이 쓰려면

EffectManager.Instance.PlayOneShot(id,position); 식으로 함수만 호출해서 쓰면 되는데, 간혹 이펙트를 직접 관리하고 싶다거나 하면 SpawnEffect 해서 직접 다뤄도 될 것 같음. 대신 이 경우엔 반드시 Release해주는 것 잊지말기…


다음은 SoundManager.cs

viewimage.php?id=2abcdd23dad63db0&no=24b0d769e1d32ca73cec81fa11d02831ce3cef1b9542c00ceb084620f9a3823a446e629c8148f2cd474db838d40bd2198bb7c35981296951fe1b9825c4a000b59772a8


사운드매니저는 AudioSource를 ObjectPool로 관리하는 싱글톤클래스로 만들었고, 각종 효과음이나 BGM을 재생하기 편하게 만들어둠. 여기다가 추가적으로 BGM전환시에 DOTween 기능 이용해서 블렌딩도 가능하게끔 해봤음.

지금 BGMSource랑 SFXSource를 분리시켜놨는데 이 부분은 StopBgmAll이나 StopSfxAll 하려는 의도도 있었지만, 더 큰 이유로는 나중에 SFX Volume이랑 BGM Volume을 따로 컨트롤 할 수 있게끔 하려고 나눠놓은거임. 아직 InGame Data쪽 프레임워크를 어떻게 가져갈지 결정을 안해서 해당 기능을 구현을 못해놨다…

기타 플레이 관련된 부분은 EffectManager랑 비슷하니 뭐 넘어감. 



아 글고 코드올리는거 고민 좀 해보다가 https://carbon.now.sh/ 라는 사이트 이용해서 이미지화 시켜봤음. 코드 긁어서 가져가는건 불가능해도 이게 더 보기 편하겠지??

개발하다가 정신나갈 것 같을때 잠깐 글쓰러 오는데.. 막상 쓰고 보니 주석도 없는데 쓸데없이 코드 전문 올렸나 싶기도 하다.


지금 프레임워크 올리는 것들은 혹시나 필요한사람 참고하던지 가져다 쓰라고 올리는건데 이미지로 올리면 코드를 못 가져가니깐...

아마 3편으로 끝날테니 3편에서 소스를 파일로 올리던가 할듯...?


나는 앞으로 개발 할 때마다 이번에 만든 프레임워크 써보면서 개선하려 하는데, 관심 있는 사람은 써보거나 코드 보고 피드백 주면 고맙겠음..


다음으로 Global Message 방식이랑 그거 이용한 UI 헬퍼 짤막하게 하고 프레임워크쪽은 끝..