2024. 10. 12. 01:22ㆍ코드 전시관/Unity
지금 진행하는 프로젝트에 다양한 장비를 여러 개 장착하는 기능이 있습니다.
여기서 각 부품은 0~3개의 다양한 스킬을 가지고 있습니다.
이전 프로젝트에서 스킬들을 컴포넌트로 관리하는 것이 유리하다는 것을 알고 있었습니다.
그런데 이 스킬들을 모두 다른 컴포넌트로 사용하려면 다른 .cs파일을 사용해야합니다.
장비와 스킬의 종류가 많아지면 이것들을 수정하는 것도 굉장히 힘든 일이 됩니다.
그래서 스킬들을 각 장비의 Nested class로 사용하려 했는데, 유니티에서 Nested class는 컴포넌트가 될 수 없습니다.
(한 스크립트에 한 컴포넌트만 사용할 수 있습니다)
처음에는 각 장비에 모든 스킬에 대한 정보를 인스펙터에서 받게 했었는데,
장비에 스킬이 두세개씩 달리면서 이름 짓기도 힘들고, 무의미하게 변수들을 복사해주는 코드가 길게 작성돼 유지보수가 힘들어졌습니다.
동료 프로그래머가 아이디어를 내, 가상의 컴포넌트가 있고 스킬의 각 속성들을 인스펙터를 통해 받았다가,
런타임에 해당 스킬 컴포넌트를 AddComponent하면서 값들을 복사해주는걸 만드는게 어떻겠냐고 해 시작해봤습니다.
그렇게 NestedClassMirror라는 컴포넌트를 만들었습니다.
이 컴포넌트는 Reflection을 이용해 장비 컴포넌트의 Nested class 컴포넌트 중 하나를 선택해
가상의 게임오브젝트를 만들어 그 컴포넌트를 붙이고 그 인스펙터를 미러링합니다.
그리고 이 컴포넌트는 값이 수정되면 원본 컴포넌트의 값들을 Json 형태로 저장합니다.

실제로 저장된 값들을 Debug 모드로 조회한 모습입니다.
그런데 여기서 보이듯이, Json Conversion 함수를 사용하면 유니티 오브젝트(애셋들)에 대한 레퍼런스가 instanceID로 저장되고 있습니다.
이 instanceID는 유니티 또는 런타임을 실행할 때마다 바뀌는 값이기도 하지만, 연결된 애셋들을 유니티 에디터가 탐지하지 못해 빌드에 포함시키지 못한다는 문제가 있습니다.
처음에는 이 instanceID가 레퍼런스하는 애셋을 찾아서 경로를 저장할까 하기도 했지만, 그 많은 애셋을 하나하나 Resources 폴더에 옮기는 것은 불가능했습니다.
최종적으로는 유니티가 감지할 수 있는 Serialization 방식을 사용하기위해 Object 레퍼런스를 저장하는 방식을 사용했습니다.
또 유니티 오브젝트가 아닌 C# Raw Class나 List 등을 저장할 필요도 있어 이를 위해 단순한 string key-value pair가 아닌 SerializedEntry라는 것을 만들어 일종의 트리 구조로 관리하게 변경했습니다.

각 SerializedEntry는 string 또는 object 값을 가지고, 추가로 NestedEntries (SerializedEntry의 List)를 가져 Raw Class의 속성들이나 List 등을 재귀적으로 Serialize할 수 있게 만들었습니다.
이를 개발하기 위해 유니티의 SerializedProperty 기능을 활용해, 한 클래스의 Serialize 대상인 모든 property를 dfs 방식으로 순회하며 재귀적으로 Serialize하게 했습니다.
또 런타임에서 Deserialize 할 땐 SerializedProperty를 사용할 수 없으므로 Reflection을 활용하여 각 속성들을 초기화해줬습니다.

이제 애셋들을 직접 레퍼런스하고 있기 때문에 유니티가 빌드에 자동으로 포함시킬 수 있게 됐습니다.
장비들이 강화버전도 있는데, Prefab variant에서 변경된 부분을 표시해주는 기능까지 추가했습니다.

소스코드는 아래에서 확인하실 수 있습니다.
제네릭을 이용해 만들고싶었는데, 커스텀 에디터도 사용해야하고 해서 BaseClass라는 type alias를 사용했습니다.
HappyKit/Assets/Scripts/HappyKit/BaseClasses/NestedClassMirror at main · HappyFaceFriend/HappyKit
Contribute to HappyFaceFriend/HappyKit development by creating an account on GitHub.
github.com
'코드 전시관 > Unity' 카테고리의 다른 글
[HappyKit] 다양한 Singleton 구현 (0) | 2024.10.29 |
---|---|
[HappyKit] C# Extension Method를 활용한 Vector 변환 기능 (0) | 2024.05.04 |
[Unity] 원활한 카메라 활용을 위한 CameraToken (0) | 2023.12.29 |
[HappyTools] GameBootstrapper, SingletonBehaviour (0) | 2023.03.21 |
[HappyTools] StateMachineBase (0) | 2023.03.13 |