무엇을 찾고 계신가요?
Hero background image
스크립터블 오브젝트로 게임 데이터와 로직 분리하기
이 페이지는 기계 번역되었습니다. 정확한 정보 출처로 원본 버전을 보려면 우측 링크를 참고하세요.

이 페이지에서는 스크립터블 오브젝트를 게임 코드의 로직과 데이터를 분리하는 데이터 컨테이너로 사용하는 방법을 설명합니다.

이 가이드는 Unity 개발자를 돕기 위해 제작된 6개의 미니 가이드 시리즈 중 두 번째 가이드입니다. 데모 전자책 ' 스크립터블 오브젝트를 사용하여 Unity에서 모듈식 게임 아키텍처 만들기'에 포함된 데모입니다.

이 데모는 고전적인 공과 패들 아케이드 게임 메커니즘에서 영감을 얻은 것으로, 스크립터블 오브젝트가 테스트 가능하고 확장 가능하며 디자이너 친화적인 컴포넌트를 만드는 데 어떻게 도움이 되는지 보여줍니다.

전자책, 데모 프로젝트 및 이 미니 가이드는 함께 프로그래밍 디자인 패턴을 사용하기 위한 모범 사례를 제공합니다. 프로그래밍 디자인 패턴 을 사용하는 모범 사례를 제공합니다. 이러한 팁은 코드를 간소화하고 메모리 사용량을 줄이며 코드 재사용성을 높이는 데 도움이 될 수 있습니다.

이 시리즈에는 다음 문서가 포함되어 있습니다:

시작하기 전 중요 참고 사항

스크립터블 오브젝트 데모 프로젝트와 이 미니 가이드 시리즈를 살펴보기 전에, 디자인 패턴의 핵심은 아이디어에 불과하다는 점을 기억하세요. 모든 상황에 적용되지는 않습니다. 이러한 기술을 통해 Unity 및 스크립터블 오브젝트로 작업하는 새로운 방법을 배울 수 있습니다.

각 패턴에는 장단점이 있습니다. 특정 프로젝트에 의미 있게 도움이 되는 것만 선택하세요. 디자이너가 Unity 에디터에 크게 의존하고 있나요? 스크립터블오브젝트 기반 패턴은 개발자와의 협업을 돕는 좋은 선택이 될 수 있습니다.

궁극적으로 가장 좋은 코드 아키텍처는 프로젝트와 팀에 맞는 아키텍처입니다.

tab2
데이터 컨테이너

소프트웨어 개발자는 애플리케이션을 더 작은 독립된 단위로 세분화하는 모듈화에 관심을 갖는 경우가 많습니다. 각 모듈은 애플리케이션 기능의 특정 측면을 담당하게 됩니다.

Unity에서 스크립터블 오브젝트는 데이터와 로직을 분리하는 데 도움이 될 수 있습니다.

스크립터블 객체는 특히 정적 데이터 저장에 탁월합니다. 따라서 게임 통계, 아이템이나 NPC의 설정 값, 캐릭터 대화 등에 이상적입니다.

게임플레이 데이터를 동작 로직에서 분리하면 프로젝트의 각 독립적인 부분을 테스트하고 유지 관리하기가 더 쉬워집니다. 이러한 '우려 사항의 분리'는 필요한 변경을 수행할 때 의도하지 않은 원치 않는 부작용을 줄일 수 있습니다.

tab3
일반 워크플로

스크립터블 오브젝트 워크플로에 대해 다시 한 번 살펴보고 싶다면 이 Unity 학습 문서를 참조하세요. 그렇지 않은 경우 간단한 설명이 있습니다:

스크립터블 오브젝트를 정의합니다: 만들려면 저장하려는 데이터에 대한 필드 및 속성을 사용하여 ScriptableObject 기본 클래스를 상속하는 C# 클래스를 정의합니다. 스크립터블 오브젝트는 모노비헤이비어에서 사용할 수 있는 동일한 데이터 유형을 저장할 수 있으므로 다용도 데이터 컨테이너로 활용할 수 있습니다. 프로젝트에서 에셋을 더 쉽게 만들 수 있도록 에디터에서 CreateAssetMenuAttribute를 추가합니다.

에셋을 만듭니다: 스크립터블 오브젝트 클래스를 정의한 후에는 프로젝트에서 해당 스크립터블 오브젝트의 인스턴스를 만들 수 있습니다. 이는 디스크에 저장된 에셋으로 나타나며 다른 게임 오브젝트와 씬에서 재사용할 수 있습니다.

값을 설정합니다: 에셋을 만든 후 인스펙터에서 필드 및 속성 값을 설정하여 데이터로 채웁니다.

에셋을 사용합니다: 에셋에 데이터가 저장되면 변수나 필드에서 데이터를 참조합니다. 스크립터블 오브젝트 에셋에 대한 모든 변경 사항은 전체 프로젝트에 반영됩니다.

스크립터블 오브젝트를 게임의 여러 부분에 걸쳐 데이터 컨테이너로 용도를 변경할 수 있습니다. 예를 들어 스크립터블 오브젝트 내에서 무기나 캐릭터의 프로퍼티를 정의한 다음 프로젝트의 어느 곳에서나 해당 에셋을 참조할 수 있습니다.

참고: 런타임에 CreateInstance 메서드를 통해 스크립터블 오브젝트를 생성할 수도 있습니다. 그러나 데이터 저장의 경우 일반적으로 CreateAssetMenuAttribute를 사용하여 스크립터블 오브젝트 에셋을 미리 생성합니다.

tab4
스크립터블 객체와 모노비헤이비어 비교

스크립터블 오브젝트가 모노비헤이비어보다 데이터 저장에 더 적합한 이유를 더 잘 이해하려면 각각의 빈 버전을 비교해 보세요. 에셋 직렬화를 모드로 설정해야 합니다: 프로젝트 설정에서 텍스트 를 강제로 설정하면 YAML 마크업을 텍스트로 볼 수 있습니다.

비어 있는 모노비헤이비어로 새 게임 오브젝트를 생성합니다. 그런 다음 빈 스크립터블 오브젝트 에셋과 비교합니다. 나란히 놓으면 위 이미지와 같이 비교한 것처럼 보일 것입니다.

스크립터블 오브젝트는 모노비헤이비어에 비해 가볍고 트랜스폼 컴포넌트처럼 후자와 관련된 오버헤드가 없습니다. 이렇게 하면 스크립터블 오브젝트의 메모리 사용 공간이 줄어들고 데이터 저장에 더욱 최적화됩니다.

tab5
패턴 데모

스크립터블 오브젝트는 에셋으로 저장되므로 플레이 모드 외부에서도 유지되므로 유용할 수 있습니다. 예를 들어 스크립터블 오브젝트 데이터는 새 씬을 로드하는 경우에도 어디서나 사용할 수 있습니다.

패턴 데모 예시에는 직접 테스트해 볼 수 있는 기본 크레딧 화면이 있습니다. Credits_Data 스크립터블 객체를 수정한 다음 업데이트를 눌러 저장된 텍스트가 표시되는지 확인합니다.

대화가 많은 RPG나 튜토리얼 장면에 사전 스크립트가 있는 경우, 많은 양의 데이터를 저장하는 일반적인 방법입니다.

스크립터블 오브젝트 내의 데이터는 수정 시 즉시 업데이트되지만, 우리 프로젝트에서는 화면을 수동으로 새로 고치려면 업데이트 버튼이 필요합니다. UI 툴킷 기반 화면은 한 번만 자체적으로 빌드되며 데이터가 변경되면 알림을 받아야 합니다.

업데이트를 자동으로 동기화하려면 스크립터블 오브젝트 내에서 이벤트를 만듭니다. 예를 들어, 이 예제SO 스크립트는 예제값이 변경될 때마다 OnValueChanged 이벤트를 호출합니다. 아래 코드 예시를 보세요.

그런 다음 수신 UI 객체가 OnValueChanged를 구독하고 그에 따라 업데이트하도록 합니다.

tab6
플라이웨이트 패턴으로 게임 데이터 저장

스크립터블 오브젝트는 많은 오브젝트가 동일한 데이터를 공유할 때 빛을 발합니다. 예를 들어, 수많은 유닛의 공격 속도와 최대 체력이 동일한 전략 게임을 제작하는 경우 모든 게임 오브젝트에 해당 값을 개별적으로 저장하는 것은 비효율적입니다.

대신 공유 데이터를 중앙에 통합하고 각 개체가 해당 공유 위치를 참조하도록 할 수 있습니다. 소프트웨어 설계에서는 이를 플라이웨이트 패턴으로 알려진 최적화라고 합니다. 이러한 방식으로 코드를 재구성하면 많은 값을 복사하는 것을 방지하고 메모리 사용량을 줄일 수 있습니다.

패들볼소에서는 게임데이터소 스크립터블 오브젝트가 공유 데이터 저장소 역할을 합니다.

패들 및 볼 스크립트는 일반적인 설정(속도, 질량, 물리 탱탱함 등)의 별도 복사본을 유지하는 대신 가능한 경우 동일한 GameDataSO 인스턴스를 참조합니다. 각 게임 요소는 위치 및 입력 이벤트와 같은 고유 데이터를 유지하지만 가능한 경우 기본값은 공유 데이터로 설정합니다.

두세 개의 개체만 있으면 메모리 절약 효과가 눈에 띄지 않을 수도 있지만, 공유 데이터를 편집하는 것이 일일이 수동으로 편집하는 것보다 빠르고 오류 발생 가능성이 적습니다.

예를 들어 패들 속도를 수정해야 하는 경우 한 위치에서 조정하면 모든 장면에서 두 패들을 모두 업데이트할 수 있습니다. 모노비헤이비어에 고유 필드로 저장한 경우 한 번의 잘못된 클릭으로 두 값이 쉽게 동기화되지 않을 수 있습니다.

스크립터블 오브젝트로 데이터를 오프로드하면 팀원들이 같은 씬이나 프리팹에서 작업할 때 버전 관리와 병합 충돌을 방지하는 데 도움이 됩니다.

tab7
패들볼소 게임 데이터

GameDataSO는 스크립터블 오브젝트를 데이터 컨테이너로 사용하는 방법을 보여줍니다. 패들볼소에서는 게임플레이를 구성하는 다양한 설정이 여기에 포함됩니다:

  • 패들 데이터: 패들 속도, 드래그, 질량과 같은 속성은 게임플레이 중 패들의 움직임과 물리학을 결정합니다.
  • 볼 데이터: 여기에는 공의 현재 속도, 최대 속도, 바운스 배수가 저장되어 시뮬레이션과 상호작용할 때 공의 동작을 제어합니다.
  • 데이터를 일치시킵니다: GameDataSO에는 경기 중 포인트 간 지연에 대한 정보가 포함되어 있어 게임의 페이스를 조절하는 데 도움이 됩니다.
  • 플레이어 ID: PlayerIDSO 스크립터블 오브젝트는 각 플레이어의 팀 식별(예: Player1 및 Player2)으로 작동합니다.
  • 플레이어 스프라이트: 이 옵션 스프라이트는 플레이어 아바타 커스터마이징을 가능하게 합니다.
  • 레벨 레이아웃: LevelLayoutSO 오브젝트는 플레이어의 시작 위치와 골대, 벽과 같은 게임 요소를 정의합니다.

이러한 설정과 데이터를 모두 중앙에서 관리할 수 있는 GameDataSO를 사용하면 모든 오브젝트가 이 공유 데이터를 활용할 수 있습니다. 이렇게 하면 이러한 개체를 관리하는 방법이 간소화되고 프로젝트 전체에서 일관성을 높일 수 있습니다. 패들 물리학을 바꾸시겠습니까? 여러 스크립트를 조정하는 대신 여기에서 한 번만 변경하세요.

tab10
이중 직렬화 예시: 레벨 레이아웃

때로는 케이크도 먹고 싶을 때가 있습니다. 이중 직렬화를 사용하면 스크립터블 객체에 데이터를 저장하면서 동시에 다른 형식으로 유지할 수 있습니다.

LevelLayoutSO 스크립트는 이 개념을 보여줍니다. 패들과 공의 시작 위치를 유지하는 것 외에도 벽과 골대에 대한 변환 데이터를 사용자 지정 구조에 저장합니다.

이러한 값은 ExportToJson 메서드를 통해 디스크에 기록할 수 있습니다. JSON 파일은 사람이 읽을 수 있는 텍스트로, Unity 외부에서 바로 수정할 수 있습니다. 이렇게 하면 에디터에서 스크립터블 오브젝트로 작업한 다음 해당 데이터를 JSON 또는 XML 파일과 같은 다른 위치에 저장할 수 있습니다.

JSON 및 XML과 같은 파일 포맷은 에디터에서 작업하기 어려울 수 있지만, Unity 외부에서는 텍스트 에디터로 쉽게 수정할 수 있습니다. 이로써 커스텀 또는 사용자 수정 레벨의 가능성이 열립니다.

그런 다음 GameSetup 스크립트는 LevelLayout ScriptableObject 또는 외부 JSON 파일을 사용하여 게임 레벨을 생성할 수 있습니다.

커스텀 모드 레벨을 로드하기 위해 설치 스크립트는 런타임에 CreateInstance를 사용하여 스크립터블 오브젝트를 생성합니다. 그런 다음 JSON 파일에서 텍스트를 읽어 스크립터블 오브젝트를 채웁니다.

커스텀 데이터는 스크립터블 오브젝트의 콘텐츠를 대체하고 외부에서 수정한 레벨을 다른 레벨처럼 사용할 수 있게 해줍니다. 나머지 애플리케이션은 스위치를 인식하지 못한 채 정상적으로 작동합니다.

tab11
스크립터블 오브젝트 데이터 컨테이너의 다른 용도

패들볼 미니 게임으로 스크립터블객체 데이터 컨테이너의 모든 사용 사례를 보여드릴 수는 없지만, 여러분의 애플리케이션에 맞게 다음 사항을 고려해 보세요:

  • 게임 구성: 상수, 게임 규칙 또는 게임 플레이 중에 변경할 필요가 없는 기타 설정 매개변수에 대해 생각해 보세요. 그러면 다른 컴포넌트는 하드코딩된 값을 사용하지 않고도 이 구성 데이터를 참조할 수 있습니다.
  • 캐릭터 및 적 속성: 스크립터블 오브젝트를 사용하여 체력, 공격력, 속도 등과 같은 속성을 정의할 수 있습니다. 이를 통해 디자이너는 개발자 없이도 게임플레이 요소의 밸런스를 조정하고 조정할 수 있습니다.
  • 인벤토리 및 아이템 시스템: 이름, 설명, 아이콘과 같은 항목 정의 및 속성은 스크립터블 오브젝트에 적합합니다. 플레이어가 수집, 사용 또는 장착한 아이템을 추적하는 인벤토리 관리 시스템의 일부로 사용할 수도 있습니다.
  • 대화 및 내러티브 시스템: 스크립터블 오브젝트는 대화 텍스트, 캐릭터 이름, 분기 대화 경로 및 기타 내러티브 관련 데이터를 저장할 수 있습니다. 복잡한 대화 시스템의 기반을 마련할 수 있습니다.
  • 레벨 및 진행 상황 데이터: 스크립터블 오브젝트를 사용하여 레벨 레이아웃, 적 스폰 지점, 목표 및 기타 레벨 관련 정보를 정의할 수 있습니다.
  • 오디오 클립: 패들볼소 프로젝트에서 볼 수 있듯이 스크립터블 오브젝트는 하나 이상의 오디오 클립을 저장할 수 있습니다. 게임의 여러 부분에 걸쳐 오디오 효과나 음악을 정의할 수 있습니다.
  • 애니메이션 클립: 스크립터블 오브젝트는 애니메이션 클립을 저장하는 데 사용할 수 있으며, 여러 게임 오브젝트 또는 캐릭터에서 공유되는 공통 애니메이션을 정의하는 데 유용합니다.

스크립터블 오브젝트에 대해 자세히 알아보고 자신의 프로젝트에 맞게 조정하면 더 많은 응용 분야를 발견할 수 있습니다. 특히 데이터 관리에 유용하며 다양한 게임 요소에서 일관성을 쉽게 유지할 수 있습니다.

스크립트 가능한 아웃트로
스크립터블 오브젝트 리소스 추가

스크립터블 오브젝트를 사용한 디자인 패턴에 대한 자세한 내용은 전자책에서 확인하세요. 스크립터블 오브젝트로 Unity에서 모듈식 게임 아키텍처 만들기. 다음에서 일반적인 Unity 개발 디자인 패턴에 대해 자세히 알아볼 수도 있습니다. 게임 프로그래밍 패턴으로 코드 수준 높이기.

이 콘텐츠가 마음에 드셨나요?