본문 바로가기

Unity

Unity의 ScriptableObject의 활용법

ScriptableObject

유니티의 공식 문서(https://docs.unity3d.com/kr/current/Manual/class-ScriptableObject.html)에는 스크립터블 오브젝트를 다음과 같이 정의하고 있다.

ScriptableObject는 클래스 인스턴스와는 별도로 대량의 데이터를 저장하는 데 사용할 수 있는 데이터 컨테이너입니다. ScriptableObject의 주요 사용 사례 중 하나는 값의 사본이 생성되는 것을 방지하여 프로젝트의 메모리 사용을 줄이는 것입니다. 이는 연결된 MonoBehaviour 스크립트에 변경되지 않는 데이터를 저장하는 프리팹이 있는 프로젝트의 경우 유용합니다.

 

이리저리 꼬아놨지만, 결론적으로는 어떤 데이터를 에셋 형태로 저장하는 기능이다. 스크립터블 오브젝트를 사용해서 프로그램에서 사용하는 여러가지 데이터를 표현하고 편집할 수 있다. 

 


공식에서 이야기하는 사용 사례

유니티 사이트에서 찾아볼 수 있는 사용 사레 (https://unity.com/kr/how-to/architect-game-code-scriptable-objects)를 참고해 보자. 이 글에서는 플레이어의 HP를 스크립터블 오브젝트로 사용하고 체력 UI에서 해당 스크립터블 오브젝트를 참조하면, 플레이어의 HP가 변경됐을 때 체력 UI가 참조하는 스크립터블 오브젝트에서도 값이 같이 변경된다고 이야기한다. 

 

 

그런데 생각해보면 이런 특성은 일반적인 클래스여도 똑같이 가지는 특성이다. 위의 링크 뿐만 아니라 다른 곳들에서 스크립터블 오브젝트의 장점 등을 찾아보면 여러 오브젝트가 하나의 스크립터블 오브젝트를 참조하더라도 메모리에 단 한개만 생성되기 때문에 메모리도 절약된다는 식의 이야기가 많이 있는데, 이 또한 엄밀히 말하면 스크립터블 오브젝트의 특성이 아니라 그냥 C# 클래스의 특성, 그리고 Flyweight 패턴으로 짜여진 코드의 특징일 뿐이다.

 

그러면 스크립터블 오브젝트는 진짜 뭐가 다르고 어디다 써야 할까?

 

요약하면 스크립터블 오브젝트는 유니티 에디터과 통합되어있지만 GameObject는 아닌 클래스 인스턴스이다.

 

유니티 에디터와 통합되어 있기 때문에 에디터에서 생성, 삭제 등을 할 수 있고 GameObject에 바인딩도 가능하며 플레이모드에서 실시간으로 값 노출도 가능하다. 그 말은, 달리 말하면 유니티 에디터에서 직접 데이터를 다룰 경우에만 스크립터블 오브젝트가 유용하다는 뜻이다. 현재 보통의 한국 게임업계에선 여러가지 이유로 에디터에서 직접 컨텐츠를 작업하는 경우는 드물다. 일반적인 컨텐츠는 데이터 테이블로 이루어져있으며, 원본이 엑셀인 만큼 스크립터블 오브젝트를 사용할만한 경우는 많지 않다.


구체적인 활용 예를 든다면?

에디터에서 무언가 작업할 경우나, 에디터에 데이터를 통합시킬 필요가 있을 경우 사용한다고 생각하면 어느 정도 맞다. 대표적인 예로는 인하우스 툴의 데이터 저장 용도로 사용하는 것을 들 수 있다.

 

아무리 컨텐츠가 테이블 위주라고 해도, 테이블로 작업하기 어려운 경우가 있고 그럴 경우 보통 편집툴을 만들게 된다. 예를 들면 액션게임에서의 스킬 툴이 있다. 이런 경우 정확한 위치와 시간에 판정이 있어야 하기 때문에 테이블로 작업하긴 어렵고, 전용 스킬 편집 툴을 제작해서 직접 재생하고 조정해가면서 작업하게 된다.

 

이런 경우 툴로 생성한 데이터를 저장하고 사용하는데 스크립터블 오브젝트를 쓰면 별도의 저장하고 불러오는 코드를 만들 필요가 없는 것은 물론, 에디터 화면과도 쉽게 연동시킬 수 있다.

 

다른 케이스로는 기획자가 잘 안만지는, 프로그래머나 아티스트가 입력하고 관리하는 데이터를 다루는 데 쓸 수 있다. 예를 들자면 빌드 등에 쓰이는 파라미터나, 순수 연출을 위한 여러가지 파라미터나 애니메이션 커브 등이 있을 수 있다. 특히 스크립터블 오브젝트여서 가지는 특별한 장점이 있는데, 실행 중에 스크립터블 오브젝트 에셋의 값을 조절할 경우 실시간으로 조절된 값이 반영된다는 것이다. 실행중에 직접 수정해가면서 확인해야 할 데이터가 있을 경우 스크립터블 오브젝트를 사용하기에 가장 좋은 곳이라고 생각해도 좋다.

 

또 다른 사용예로는 반드시 GameObject일 필요가 없는 MonoBehaviour를 대체하는 것이다. MonoBehaviour인데 Awake나 Update등의 메서드를 사용하지 않고 있는 것이 있다면, 십중팔구는 스크립터블 오브젝트로 대체할 수 있다. 불필요한 오브젝트가 생성되어 있는 것은 관리에도 성능에도 좋지 않으므로 스크립터블 오브젝트로의 대체를 고려해 볼 만 하다. 예를 들면 게임에서 사용할 폰트나 설정값 등을 간단히 로드하고 참조하고 싶어서 아무 일도 하지 않는 빈 게임오브젝트에 스크립트를 달고 인스펙터에 Font 등을 노출시켜본 경험이 한번쯤은 있을 것이다. 이런 경우에 MonoBehaviour보다는 스크립터블 오브젝트의 사용을 고려해야 한다.