
이 페이지에서는 스크립터블 오브젝트를 로직 컨테이너로 사용하는 방법을 설명합니다. 이렇게 하면 델리게이트 오브젝트나 필요할 때 호출할 수 있는 작은 액션 번들로 취급할 수 있습니다.
이 전자책과 함께 제공되는 Unity 개발자 데모를 지원하기 위해 제작된 6개의 미니 가이드 시리즈의 네 번째 가이드입니다. ScriptableObjects로 Unity에서 모듈식 게임 아키텍처 만들기.
이 데모는 고전적인 볼 및 패들 아케이드 게임 메카닉에서 영감을 얻었으며, 스크립터블 오브젝트를 사용하여 테스트 가능하고 확장 가능하며 디자이너 친화적인 컴포넌트를 제작하는 방법을 보여 줍니다.
전자책, 데모 프로젝트 및 이 미니 가이드는 Unity 프로젝트에서 ScriptableObject 클래스와 함께 프로그래밍 디자인 패턴을 사용하는 베스트 프랙티스를 제공합니다. 다음 팁을 통해 코드를 단순화하고, 메모리 사용량을 줄이고, 코드 재사용성을 높일 수 있습니다.
이 시리즈에는 다음과 같은 문서가 포함되어 있습니다.
스크립터블 오브젝트 데모 프로젝트와 이 시리즈의 미니 가이드를 살펴보기 전에 디자인 패턴은 단순히 아이디어라는 점을 기억하세요. 모든 상황에 적용되는 것은 아닙니다. 이 기술을 통해 Unity 및 스크립터블 오브젝트를 사용하는 새로운 방법을 배울 수 있습니다.
각 패턴에는 장단점이 있습니다. 특정 프로젝트에 유의미한 부분만 선택하세요. 디자이너가 Unity 에디터를 많이 사용하나요? 스크립터블 오브젝트 기반 패턴을 사용하면 개발자와 협업하는 데 도움이 될 수 있습니다.
궁극적으로 프로젝트와 팀에 가장 적합한 코드 아키텍처가 가장 좋습니다.

전략 패턴을 사용하면 인터페이스 또는 기본 스크립터블 오브젝트 클래스를 정의한 다음 런타임 시 델리게이트 오브젝트를 서로 교환할 수 있습니다.
특정 작업을 수행하기 위한 알고리즘을 스크립터블 오브젝트에 캡슐화한 다음 다른 컨텍스트에서 해당 스크립터블 오브젝트를 사용할 수 있습니다.
예를 들어 EnemyUnit 클래스에 AI 또는 경로 탐색 시스템을 작성했다면 경로 검색 기법(A*, Dijkstra 등)을 사용하는 스크립터블 오브젝트를 만들 수 있습니다.
EnemyUnit 자체에는 실제로 경로 탐색 로직이 포함되지 않습니다. 대신 별도의 '전략' 스크립터블 오브젝트에 대한 레퍼런스를 유지합니다. 이 설계의 결과는 오브젝트를 교환하기만 하면 다른 알고리즘으로 전환할 수 있다는 것입니다. 이는 런타임에 다양한 동작을 선택하는 한 가지 방법입니다.
MonoBehaviour 작업을 수행해야 하는 경우 자체 메서드가 아닌 스크립터블 오브젝트의 외부 메서드를 호출합니다. 예를 들어 스크립터블 오브젝트에는 적 유닛을 구동하고 대상을 지정하는 MoveUnit 또는 SetTarget에 대한 공용 메서드가 포함될 수 있습니다.
추상적인 기본 클래스나 인터페이스로 이 패턴을 개선할 수 있습니다. 이렇게 하면 전략을 구현하는 모든 스크립터블 오브젝트를 다른 스크립터블 오브젝트로 교체할 수 있습니다. 핫 스와핑이 가능한 이 스크립터블 오브젝트는 런타임 시 바로 MonoBehaviour 연결되어 해당 오브젝트를 참조합니다.
게임 상태로 인해 EnemyUnit가 동작을 변경해야 하는 경우, 외부 컨텍스트(MonoBehaviour)에서 해당 조건을 확인할 수 있습니다. 그런 다음 응답으로 다른 스크립터블 오브젝트를 연결할 수 있습니다.
구현 세부 정보를 스크립터블 오브젝트로 분리하면 팀 간에 더 효과적으로 책임을 나눌 수 있습니다. 한 개발자 스크립터블 오브젝트 내의 알고리즘에 집중하고 다른 개발자는 MonoBehaviour 컨텍스트에서 작업할 수 있습니다.
이 플러그 가능한 동작을 생성하려면 다음을 수행해야 합니다.
이렇게 코드를 구성하면 동일한 전략의 다양한 구현을 더 쉽게 전환할 수 있습니다. 그러면 이러한 플러그 가능한 동작을 디버깅하고 유지 관리하기가 더 쉬워집니다.
알고리즘이나 전략은 복잡할 필요가 없습니다. 예를 들어, PaddleBallSO 프로젝트는 SimpleAudioDelegate에서 상당히 기본적인 오디오 재생 시스템을 시연합니다.
추상 클래스인 AudioDelegateSO 는 AudioSource 파라미터를 수락하는 단일 플레이 메서드를 정의합니다. 구체적인 구현은 이를 오버라이드합니다.
SimpleAudioDelegateSO 하위 클래스는 AudioClip 배열을 정의합니다. 임의의 클립을 선택하고 오버라이드된 플레이 메서드 구현을 사용하여 재생합니다. 그러면 커스텀 범위 내에서 피치와 볼륨의 배리에이션이 추가됩니다.
몇 줄에 불과하지만 아래 코드 스니핏으로 다양한 오디오 효과를 만들 수 있습니다.
이 구체적인 예시는 많은 오디오 사용에 적합하지는 않지만, 전략 패턴에서 스크립터블 오브젝트의 기본 사용 데모로 제공됩니다.
디자이너는 코드를 터치하지 않고도 음향 효과를 표현할 수 있는 다양한 스크립터블 오브젝트를 만들 수 있습니다. 또한 기본 스크립터블 오브젝트가 완료되면 개발자 지원이 최소화되어야 합니다.
PaddleBallSO에서 누구든지 이제 공이 레벨의 벽에 닿을 때 재생할 새로운 사운드 배열을 설정할 수 있습니다. 디자이너는 에디터에서만 작업하기 때문에 창의적인 독립성과 유연성을 확보할 수 있습니다. 이러한 접근 방식을 통해 프로그래밍 리소스를 확보할 수 있습니다. 개발자는 더 이상 모든 디자인 의사 결정을 지원할 필요가 없습니다.

Patterns 데모에서 오디오 예시를 확인할 수도 있습니다. 각 사운드는 인스턴스 간에 작은 배리에이션이 있는 약간 다른 SimpleAudioDelegateSO 에셋에서 파생됩니다.
이 예시에서는 각 코너에 AudioSource가 있습니다. 커스텀 AudioModifier MonoBehaviour 스크립터블 오브젝트 기반 델리게이트를 사용하여 사운드를 재생합니다.
발표 차이는 각 스크립터블 오브젝트 에셋의 설정(BeepHighPitched_SO, BeepLowPitched_SO 등)에서 발생합니다.
스크립터블 오브젝트를 사용하여 액션 로직을 제어하면 디자인 팀이 아이디어를 더 쉽게 실험할 수 있습니다. 이를 통해 디자이너는 개발자 더 독립적으로 작업할 수 있습니다.

PaddleBallSO 프로젝트는 또한 목표 시스템에서 전략 패턴을 사용합니다. 런타임에 변경할 필요는 없지만, 스크립터블 오브젝트에 각 오브젝트를 캡슐화하면 윈-프로즈 조건을 유연하게 테스트할 수 있습니다.
추상적인 기본 클래스인 ObjectiveSO에는 목표의 이름과 완료 여부와 같은 값이 있습니다.
그런 다음 ScoreObjectiveSO와 같은 구상 서브 클래스는 각 목표를 완료하는 방법에 대한 실제 로직을 구현합니다. 이를 위해 ObjectiveSO의 CompleteObjective 메서드를 오버라이드하고 Win 조건 로직을 추가합니다.
플레이어가 특정 점수를 획득하거나 특정 수의 적을 물리칠 필요가 있나요? 특정 위치 도달률 또는 특정 아이템을 픽업해야 할까요? 이는 일반적으로 스크립터블 오브젝트 기반의 목표가 될 수 있는 승리 조건입니다.
ObjectiveManager는 스크립터블 오브젝트의 더 큰 컨텍스트 역할을 합니다. 이 컴포넌트는 ObjectiveSO 목록을 유지하고 각 스크립터블 오브젝트의 완성 여부를 결정합니다. 모든 ObjectiveSO가 완료 상태를 표시하면 게임이 종료됩니다.
예를 들어 ScoreObjectiveSO는 점수 목표를 구현하는 한 가지 방법을 보여 줍니다.
ObjectiveManager는 지정된 모든 목표를 완료하는 것만 고려합니다. 각 목표 내의 세부 사항을 인식하지 못합니다.
여기서 목표는 모듈성입니다. 이렇게 하면 기존의 ObjectiveSO에 영향을 주지 않고 각 ObjectiveSO를 커스터마이즈할 수 있습니다.
PaddleBallSO 게임은 정말 단 하나의 목표를 가지고있다. 플레이어 중 하나가 승점 목표에 도달하면 게임플레이가 종료됩니다.
하지만 이를 확장하거나 목표를 결합하여 더 복잡한 목표 시스템을 만들 수도 있습니다. 새로운 게임 모드를 빌드할 수 있는지 확인해 보세요(예: 시간이 얼마 남지 않아 최소한의 포인트를 획득하세요).
로직이 스크립터블 오브젝트 내부에 캡슐화되어 있으므로 ObjectiveSO를 다른 오브젝트로 교체할 수 있습니다. 새 Win 조건을 만들려면 ObjectiveManager에서 목록을 다시 설정해야 합니다. 어떤 면에서 목표는 주변 환경에 '플러그'할 수 있습니다.
ObjectiveSO의 장점 중 하나는 게임 오브젝트 간에 메시지를 전송하는 데 사용되는 이벤트입니다. 다음으로 스크립터블 오브젝트를 사용하여 이벤트 기반 아키텍처를 구현하는 방법을 살펴보겠습니다.

ScriptableObject를 사용한 디자인 패턴에 대한 자세한 내용은 전자책 ScriptableObject를 사용하여 Unity에서 모듈식 게임 아키텍처 만들기에서 확인할 수 있습니다. 또한 일반적인 Unity 개발 디자인 패턴에 대한 자세한 내용은 게임 프로그래밍 패턴으로 코딩 업그레이드를 참조하세요.