Hero image

스크립터블 오브젝트 기반 런타임 집합을 사용하는 방법

이 웹페이지는 이해를 돕기 위해 기계 번역으로 제공됩니다. 기계 번역으로 제공되는 콘텐츠에 대한 정확도나 신뢰도는 보장되지 않습니다. 번역된 콘텐츠의 정확도에 관해 의문이 있는 경우 웹페이지의 공식 영어 원문을 참고해 주시기 바랍니다.

시작하기 전 중요 참고 사항

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

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

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

런타임 세트

스크립터블 오브젝트는 정적 데이터를 저장할 수 있습니다. 동적 데이터를 저장하도록 수정할 수도 있습니다. 이는 런타임에 게임 오브젝트 또는 컴포넌트 컬렉션을 참조할 때 특히 유용합니다.

이와 같은 '런타임 세트'는 일부 개발자가 싱글톤을 사용하는 이유, 즉 손쉬운 글로벌 액세스를 재현합니다. 안타깝게도 싱글톤에는 원치 않는 종속성 같은 짐이 따릅니다. 이러한 추가 종속성은 테스트를 복잡하게 만들고 디버깅을 더 어렵게 만들 수 있습니다.

대안으로 자주 참조되는 컴포넌트에 스크립터블 오브젝트 기반 런타임 세트를 사용하는 것을 고려해 보세요. 예를 들어, 스폰된 적, 수집품, 체크포인트와 같은 게임 요소를 추적하는 데 사용할 수 있습니다.

프로젝트 레벨 에셋인 스크립터블 오브젝트는 씬 내의 모든 오브젝트에 대한 데이터에 대한 전역 액세스를 제공합니다. 이 기능을 사용하면 싱글톤과 관련된 많은 단점 없이 정보를 공유할 수 있습니다.

기본 구현

다음은 게임 오브젝트에 대한 런타임 세트를 만드는 한 가지 방법입니다. 공개 요소 컬렉션을 보관하는 데이터 컨테이너라고 생각하면 되며, 멤버를 추가하고 제거하는 메서드도 포함되어 있습니다.

런타임에 모든 모노비헤이비어는 공용 아이템 프로퍼티를 참조하여 게임 오브젝트의 전체 목록을 가져올 수 있습니다. 다른 스크립트나 컴포넌트는 추가 또는 제거를 호출하여 항목 목록을 수정할 수 있습니다.

using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "GameObject Runtime Set", fileName
= "GORuntimeSet")]
public class GameObjectRuntimeSetSO: ScriptableObject
{

   private List<GameObject> items = new List<GameObject>();
   public List<GameObject> Items => items;

   public void Add(GameObject thingToAdd)
   {
       if (!items.Contains(thingToAdd))
            items.Add(thingToAdd);
   }

   public void Remove(GameObject thingToRemove)
   {
       if (items.Contains(thingToRemove))
            items.Remove(thingToRemove);
   } 
}

일반 버전

특정 유형의 모노비헤이비어만 추적하도록 런타임 세트를 보다 구체적으로 설정할 수 있습니다. 이 경우 각 유형에 대한 특정 세트(예: EnemyRuntimeSet, PickupRuntimeSet 등)를 생성하세요.

일반 추상 클래스를 사용하면 이 과정을 간소화할 수 있습니다. 그런 다음 이 기본 클래스에서 다른 런타임 집합을 파생할 수 있습니다. 예를 들어 커스텀 적 컴포넌트에 대한 런타임 세트를 만들고 싶다면 아래 코드 스니펫처럼 일반 RuntimeSetSO<T>와 구체적인 EnemyRuntimeSetSO의 클래스를 정의할 수 있습니다.

구체적인 클래스인 EnemyRuntimeSetSO에는 구현 세부 정보가 없고 CreateAssetMenu 어트리뷰트만 있다는 것을 알 수 있습니다.

추적하려는 각 새 컴포넌트를 관리하려면 해당 런타임 세트만 있으면 됩니다. 필요한 만큼 구체적인 클래스를 구축하세요. 적, NPC, 인벤토리 아이템, 퀘스트 등은 모두 고유한 런타임 세트를 가질 수 있습니다.

public abstract class RuntimeSetSO<T>: ScriptableObject
{
   public List<T> Items = new List<T>();

   public void Add(T thing)
   {
       if (!Items.Contains(thing))
            Items.Add(thing);
   }

   public void Remove(T thing)
   {
       if (Items.Contains(thing))
            Items.Remove(thing);
   } 
}

[CreateAssetMenu(menuName = "Enemy Runtime Set", fileName =
"EnemyRuntimeSet")]

public class EnemyRuntimeSetSO: RuntimeSet<Enemy>
{

}
불일치 오류

사용 방법 및 제한 사항

런타임 세트 관리는 사용자에게 달려 있습니다. 종종 게임 플레이 중에 두 번째 모노비헤이비어를 사용하여 설정하거나 업데이트할 수 있습니다.

컴포넌트가 세트에 자동으로 포함되도록 하려면 모노비헤이비어의 OnEnableOnDisable에서 런타임 세트의 추가 또는 제거 메서드를 호출할 수도 있습니다.

예를 들어 가상의 클래스는 아래 코드 스니펫과 같이 보일 수 있습니다.

여기서 각 컴포넌트는 OnEnable 또는 OnDisable 메서드를 사용하여 스스로를 추가하거나 제거할 수 있습니다. 인스펙터에서 m_RuntimeSet 필드가 설정되어 있으면 Enemy 컴포넌트가 EnemyRuntimeSetSO에 자동으로 나타납니다. 프리팹과 함께 컴포넌트를 사용할 때 특히 유용합니다.

이 기법의 한 가지 한계는 런타임에 스크립터블 객체를 검사하는 경우 기본적으로 인스펙터에서 항목 목록의 내용을 볼 수 없다는 것입니다.

대신 각 요소 필드에 '유형 불일치'가 표시됩니다. 설계상 스크립터블 오브젝트는 씬 오브젝트를 직렬화할 수 없습니다. 목록은 실제로 작동하지만 데이터가 올바르게 표시되지 않습니다.

혼동을 피하고 인스펙터에 목록이 표시되지 않도록 하려면 공개 속성 또는 HideInInspector 속성을 사용하세요.

사용자 지정 편집기 스크립트 및 인스펙터를 사용하여 이 문제를 해결할 수도 있습니다. 좋은 예로는 Unity 에셋 스토어의 Soap - 스크립터블 오브젝트 아키텍처 패턴 또는 아래 패턴 데모 예시를 들 수 있습니다.

public class Enemy: MonoBehaviour
{
     [SerializeField] private EnemyRuntimeSetSO m_RuntimeSet;

     private void OnEnable()
     {
         m_RuntimeSet.Add(this);
     }

     private void OnDisable()
     {
         m_RuntimeSet.Remove(this);
     }
}
런타임 세트

패턴 데모

패들볼소에는 런타임 세트에 대한 사용 사례는 없지만, 프로젝트의 패턴 데모에는 이 디자인 패턴이 작동하는 모습을 보여주는 작은 샘플이 포함되어 있습니다.

블록 스폰 버튼을 클릭하여 블록 벽을 점진적으로 채웁니다. 공이 접촉하면 블록을 파괴합니다.

세트 선택을 선택하여 인스펙터에 BlockRuntimeSet_Data를 표시합니다. 여기에는 씬의 모든 블록 목록이 포함되어 있습니다.

공이 블록을 제거하는 만큼 빠르게 그리드에 블록을 계속 채울 수 있습니다. 동시에 런타임 세트는 항목 목록에서 활발하게 변경되는 블록 수를 추적합니다.

패턴 데모는 런타임 세트로 작업할 때 몇 가지 향상된 품질을 보여줍니다:

  • 사용자 지정 검사기: 스크립터블 오브젝트는 기본적으로 씬 오브젝트를 직렬화할 수 없으므로, GameObjectRuntimeSetEditor 스크립트는 기본 유형 불일치 오류를 재정의하는 커스텀 인스펙터를 제공합니다. 인스펙터에서 블록을 클릭하여 씬 계층 구조에서 강조 표시합니다.
  • 이벤트 업데이트: 런타임 집합에는 ItemsChanged라는 System.Action이 있습니다. 이렇게 하면 항목 목록에서 멤버를 추가하거나 제거할 때 편집기 스크립트에 알립니다. 이렇게 하면 항목 목록이 변경될 때 인스펙터가 새로 고쳐집니다. 이벤트 채널은 현재 아이템 수를 커스텀 런타임셋카운터 컴포넌트에 동기화하기도 합니다. 화면 UI에 총 블록 수가 표시됩니다.
커스텀 인스펙터

런타임 세트가 도움이 되는 방법

다음에 게임 오브젝트 또는 컴포넌트의 중앙 집중식 목록이 필요할 때는 런타임 세트를 고려하세요. 찾기 연산(Object.FindObjectOfType 또는 GameObject.FindWithTag) 보다 비용이 적게 들고 싱글톤보다 문제가 적을 수 있습니다.

스크립터블 오브젝트로서 씬의 개별 게임 오브젝트에서 분리됩니다. 런타임에 자주 추적하려는 항목에 대해 필요한 만큼의 런타임 세트를 보관하세요.

런타임 세트를 사용하면 불필요한 종속성 없이 게임플레이 오브젝트를 모니터링하는 방법을 간소화할 수 있습니다. 디버깅과 테스트 중에 절약한 시간을 플레이어를 위한 새로운 게임플레이 경험을 개발하는 데 사용할 수 있습니다.

스크립트 가능한 아웃트로

스크립터블 오브젝트 리소스 추가

런타임 세트가 향후 프로젝트에 도움이 되기를 바랍니다.

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

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