Abstract
엔티티 시스템은 Instantiate / Destroy 를 대신합니다. 캐릭터·적·총알·이펙트처럼 런타임에 나타났다 사라지는 모든 것을 ShowEntity / HideEntity 로 다루고, 풀링은 프레임워크가 알아서 합니다. 게임 코드에서 가장 많이 만지게 되는 모듈입니다.
Unity 방식과 나란히 보기
하고 싶은 일 | Unity 기본 | 엔티티 |
만들기 | Instantiate(prefab) | ShowEntity(id, 로직타입, 주소, 그룹, 데이터) |
없애기 | Destroy(go) | HideEntity(entity) — 풀로 돌아간다 |
초기화 | Awake / Start | OnInit(1회) / OnShow(스폰마다) |
정리 | OnDestroy | OnHide(회수마다) |
ToyboxNightmare 에서의 실제 사용
// 적 스폰 (EnemySpawner)
int id = EntitySerialId.Next();
entityComponent.ShowEntity(
id,
typeof(Enemy), // 붙일 로직
"Zombunny", // Addressables 주소
"Enemy", // 엔티티 그룹
EnemyData.Create(id, 1, stats, position)); // OnShow 의 userData 로 도착한다
C#
복사
예제는 그룹 5개를 씁니다: Player, Enemy, Projectile, Effect, Ally. 그룹은 풀의 단위라서, 동시에 많이 뜨는 종류일수록 Instance Capacity 를 크게 잡습니다.
반드시 지킬 규칙 다섯 가지
1.
엔티티 프리팹에 로직 스크립트를 붙이지 않는다. 프레임워크가 런타임에 붙입니다. 미리 붙이면 둘이 됩니다.
2.
OnShow 에서 모든 상태를 리셋한다. 풀에서 다시 나온 인스턴스는 이전 값을 그대로 들고 있습니다.
3.
같은 엔티티에 HideEntity 는 한 번만. 두 번 부르면 예외입니다. 예제는 가드가 있는 SafeHide() 를 씁니다.
4.
Destroy / SetActive 로 치우지 않는다. 풀 관리가 깨집니다.
5.
ShowEntity 는 비동기다. 결과는 ShowEntitySuccess / ShowEntityFailure 이벤트로 옵니다. 주소가 틀리면 실패 이벤트만 오고 화면에는 아무 일도 없습니다.
확장하려면
•
새 종류의 엔티티 = EntityLogic 을 상속한 클래스 하나 + Addressables 에 프리팹 등록
•
무기를 캐릭터 손에 붙이는 식의 계층 구조 = AttachEntity
•
인스턴스화 방식 자체를 바꾸기 = EntityHelperBase 를 상속한 헬퍼 교체
이 에디션에서 다른 점: 에셋 이름 자리에 프로젝트 경로(Assets/.../Player.prefab)가 아니라 Addressables 주소를 넣습니다. 본문 예제도 주소 기준으로 고쳐 두었습니다. 본문의 "출처" 줄 번호는 원작 저장소 기준이라 이 에디션의 파일과는 어긋날 수 있습니다.
Entity System (엔티티 시스템)
관련 소스 파일 (Relevant source files)
•
Scripts/Runtime/Base/GameEntry.cs
•
Scripts/Runtime/Entity/Entity.cs
•
Scripts/Runtime/Entity/EntityComponent.cs
•
Scripts/Runtime/Entity/EntityLogic.cs
•
Scripts/Runtime/Scene/SceneComponent.cs
•
Scripts/Runtime/Sound/SoundComponent.cs
•
Scripts/Runtime/UI/UIComponent.cs
•
Scripts/Runtime/UI/UIForm.cs
•
Scripts/Runtime/UI/UIFormLogic.cs
엔티티 시스템은 자체적인 라이프사이클, 동작, 계층적 관계를 가진 게임 오브젝트를 관리하는 Unity 게임 프레임워크의 핵심 구성 요소입니다. 이는 게임에서 엔티티를 생성, 풀링, 관리하기 위한 구조화된 접근 방식을 제공합니다.
UI 시스템에 대한 유사한 패턴은 UI System을, 씬 관리에 대한 내용은 Scene Management를 참고하세요.
Architecture Overview (아키텍처 개요)
엔티티 시스템은 컴포넌트 기반 아키텍처를 따르며 Unity의 GameObject 시스템과 통합되면서도 추가적인 라이프사이클 관리 및 풀링 기능을 제공합니다.
출처:
•
Scripts/Runtime/Entity/EntityComponent.cs 18-25
•
Scripts/Runtime/Entity/Entity.cs 18-19
•
Scripts/Runtime/Entity/EntityLogic.cs 15-16
Core Components (핵심 구성 요소)
EntityComponent (엔티티 컴포넌트)
EntityComponent는 엔티티 시스템의 메인 진입 지점이며 GameEntry.GetComponent<EntityComponent>()를 통해 접근할 수 있습니다. 엔티티 그룹을 관리하고, 엔티티 작업을 처리하며, 엔티티 계층을 유지합니다.
Entity (엔티티)
Entity 클래스는 게임 월드 내의 엔티티 인스턴스를 나타내는 MonoBehaviour입니다. 이는 EntityLogic 컴포넌트의 컨테이너 역할을 하며, 엔티티 시스템과 Unity GameObject 시스템 간의 통신을 담당합니다.
주요 속성:
•
Id: 엔티티 고유 식별자
•
EntityAssetName: 엔티티를 로드하는 데 사용되는 에셋 이름
•
EntityGroup: 엔티티가 속한 그룹
•
Logic: 엔티티 동작을 구현하는 EntityLogic 컴포넌트
EntityLogic (엔티티 로직)
EntityLogic은 반드시 상속받아 사용자 정의 엔티티 동작을 구현해야 하는 기본 클래스입니다. 이는 UIFormLogic과 유사한 패턴을 따르며, 엔티티 시스템에 연결된 라이프사이클 메서드를 제공합니다.
출처:
•
Scripts/Runtime/Entity/EntityLogic.cs 15-202
•
Scripts/Runtime/Entity/Entity.cs 18-280
Entity Lifecycle (엔티티 라이프사이클)
엔티티는 프레임워크 내에서 잘 정의된 라이프사이클을 따릅니다.
출처:
•
Scripts/Runtime/Entity/EntityLogic.cs 99-142
•
Scripts/Runtime/Entity/Entity.cs 82-189
Entity Groups (엔티티 그룹)
엔티티 그룹은 효율적인 관리를 위해 엔티티를 분류합니다. 각 그룹은 자체 엔티티 인스턴스를 유지하며, 풀링과 라이프사이클 관리에 대해 서로 다른 설정을 가질 수 있습니다.
프로그래밍적으로 그룹 추가 예시:
GameEntry.GetComponent<EntityComponent>().AddEntityGroup(
"Player", // 그룹 이름
10f, // 인스턴스 자동 해제 주기
16, // 인스턴스 용량
60f, // 인스턴스 만료 시간
0 // 인스턴스 우선순위
);
C#
복사
출처:
•
Scripts/Runtime/Entity/EntityComponent.cs 213-233
Entity Hierarchy (엔티티 계층 구조)
엔티티 시스템은 부모-자식 관계를 지원하여 복잡한 오브젝트 계층과 컴포넌트 기반 설계를 가능하게 합니다.
엔티티가 연결될 때:
•
부모 엔티티의 OnAttached 메서드 호출
•
자식 엔티티의 OnAttachTo 메서드 호출
•
자식 엔티티의 Transform이 지정된 Transform에 부모로 설정됨
출처:
•
Scripts/Runtime/Entity/EntityLogic.cs 146-182
•
Scripts/Runtime/Entity/Entity.cs 191-262
Working with Entities (엔티티 다루기)
Creating and Showing Entities (엔티티 생성 및 표시)
// 기본 엔티티 생성
GameEntry.GetComponent<EntityComponent>().ShowEntity<PlayerEntity>(
1, // 엔티티 ID
"Girl", // Addressables 주소
"Player" // 엔티티 그룹 이름
);
// 우선순위 및 사용자 데이터 포함
GameEntry.GetComponent<EntityComponent>().ShowEntity<PlayerEntity>(
1, "Girl", "Player", 100, userData
);
C#
복사
출처:
•
Scripts/Runtime/Entity/EntityComponent.cs 394-495
Hiding Entities (엔티티 숨기기)
// ID로 숨기기
GameEntry.GetComponent<EntityComponent>().HideEntity(1);
// 참조로 숨기기
Entity entity = GameEntry.GetComponent<EntityComponent>().GetEntity(1);
GameEntry.GetComponent<EntityComponent>().HideEntity(entity);
C#
복사
출처:
•
Scripts/Runtime/Entity/EntityComponent.cs 501-550
Attaching Entities (엔티티 연결하기)
// 기본 연결
GameEntry.GetComponent<EntityComponent>().AttachEntity(childEntityId, parentEntityId);
// 특정 부모 Transform 경로 지정
GameEntry.GetComponent<EntityComponent>().AttachEntity(childEntityId, parentEntityId, "Socket_RightHand");
// 특정 부모 Transform 컴포넌트 지정
GameEntry.GetComponent<EntityComponent>().AttachEntity(childEntityId, parentEntityId, parentTransform);
C#
복사
출처:
•
Scripts/Runtime/Entity/EntityComponent.cs 686-930
Implementing Custom Entity Logic (사용자 정의 엔티티 로직 구현)
using UnityGameFramework.Runtime;
public class PlayerEntity : EntityLogic
{
protected override void OnInit(object userData)
{
base.OnInit(userData);
// 플레이어 상태, 컴포넌트 초기화
}
protected override void OnShow(object userData)
{
base.OnShow(userData);
// 플레이어 활성화 시 동작 (애니메이션, 행동 시작 등)
}
protected override void OnHide(bool isShutdown, object userData)
{
// 숨김 시 정리 (사운드 정지, 행동 비활성화 등)
base.OnHide(isShutdown, userData);
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
// 매 프레임 플레이어 로직 업데이트
}
}
C#
복사
출처:
•
Scripts/Runtime/Entity/EntityLogic.cs 99-191
Entity Visibility and Availability (엔티티 가시성 및 사용 가능 여부)
EntityLogic 클래스는 두 가지 중요한 상태를 제공합니다:
•
Available: 엔티티가 표시되거나 상호작용할 준비가 되었는지
•
Visible: 엔티티가 현재 씬에서 보이는지
// 엔티티 사용 가능 여부 확인
bool isAvailable = entityLogic.Available;
// 엔티티 가시성 확인
bool isVisible = entityLogic.Visible;
// 엔티티를 보이거나 숨기기
entityLogic.Visible = true; // 또는 false
C#
복사
출처:
•
Scripts/Runtime/Entity/EntityLogic.cs 51-86
Entity Queries (엔티티 쿼리)
엔티티 시스템은 엔티티를 찾고 접근하기 위한 여러 메서드를 제공합니다.
EntityComponent entityComponent = GameEntry.GetComponent<EntityComponent>();
// 엔티티 존재 여부 확인
bool hasEntity = entityComponent.HasEntity(1);
// ID로 엔티티 가져오기
Entity entity = entityComponent.GetEntity(1);
// 에셋 이름(Addressables 주소)으로 엔티티 가져오기
Entity[] entities = entityComponent.GetEntities("Zombunny");
// 모든 로드된 엔티티 가져오기
Entity[] allEntities = entityComponent.GetAllLoadedEntities();
C#
복사
출처:
•
Scripts/Runtime/Entity/EntityComponent.cs 236-365
Integration with Other Systems (다른 시스템과의 통합)
엔티티 시스템은 다음 시스템들과 통합됩니다:
•
Resource System: 엔티티 에셋 로딩
•
Object Pool System: 엔티티 인스턴스 풀링
•
Event System: 엔티티 관련 이벤트
이 통합은 EntityComponent를 통해 초기화 시 자동으로 이루어집니다.
출처:
•
Scripts/Runtime/Entity/EntityComponent.cs 108-147
Best Practices (베스트 프랙티스)
•
엔티티 그룹으로 조직화: 서로 다른 엔티티 유형에 대해 논리적인 그룹 생성
•
풀링 최적화: 게임 요구 사항에 맞는 인스턴스 용량 및 만료 시간 구성
•
계층 구조 활용: 부모-자식 관계를 사용해 복합 엔티티 구성
•
완전한 라이프사이클 구현: 모든 라이프사이클 메서드 올바르게 구현
•
UserData를 통한 데이터 전달: 시스템 간 필요한 정보 전달 시 userData 활용
•
직접적인 GameObject 접근 피하기: GameObject 조작 대신 엔티티 시스템 API 사용









