DOTS를 배워보자 : 기초부터 차근차근

네,가능합니다 ㅣ 2024. 11. 15. 22:18

오늘부터는DOTS를 배워보려고 한다.

무거운 기능들을 지금의 개발환경에서 원하는 부분만 따로 적용할 수 있다는 사실에 배워보고싶어서

오늘부터 시작해보려고 한다.

 

1.ECS 의 기본 이해

  • ECS는 DOTS의 핵심이며, 게임 객체를 관리하는 새로운방식이다.기존 GameObject와 MonoBehaviour의 방식과달리 데이터와 행동  을 완전히 분리해서 관리한다.
  • 기본적으로 Entity, Component, System이어떻게 서로연결되는지 이해하는것이 필요하다.
  • Entity : 단순히 식별자 역할만하는 객체이다. 데이터나 기능도 없고 컴포넌트를 모아주는 역할을 한다. 
  • Component : 데이터만 보유하는 구조체 이다. 속도, 위치 등의 데이터만 해당한다. 동작(메서드) x
  • System : 컴포넌트를조작하는로직이다. 예를 들면 모든 Entity의 위치를 업데이트 하거나 충돌을 체크하는 등의 행동 로직을 담당한다.

 

아직 이해가 잘 안된다.

 

실제게임에서 사용할 수 있는 예제를 만들어보자.

 

목표

여러 적캐릭터가 플레이어를향해 자동으로 이동하는 시스템 구현

DOTS의 ECS를 사용해 적 캐릭터의 위치를 효율적으로 업데이트 하기

 

예제 설명

1. 플레이어는 기존 GameObject로 설정, 적은 DOTS의 Entity로 다룬다.

2. 적 캐릭터들은 매 프레임 플레이어의 위치를 확인하고 플레이어방향으로 이동한다.

 

준비할것

Entities패키지 설치

 

시작하기

1. 적 컴포넌트 정의하기  (아까 얘기했듯 데이터를 들고있다.)

using Unity.Entities;

public struct ChaseComponent : IComponentData
{
    public float speed;
}

 

2. 적 생성 시스템 (아까 얘기했듯 로직이 들어있다.)

using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using UnityEngine;

public class EnemySpawnerSystem : MonoBehaviour
{
    public GameObject enemyPrefab;
    public int enemyCount = 10;

    private EntityManager entityManager;

    void Start()
    {
        entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;

        // 엔티티 아키타입 생성
        EntityArchetype archetype = entityManager.CreateArchetype(
            typeof(Translation), // 위치
            typeof(Rotation), // 회전
            typeof(ChaseComponent) // 추격 컴포넌트
        );

        // 적 엔티티 생성
        for (int i = 0; i < enemyCount; i++)
        {
            Entity enemyEntity = entityManager.CreateEntity(archetype);
            entityManager.SetComponentData(enemyEntity, new Translation { Value = new float3(i * 2, 0, 0) });
            entityManager.SetComponentData(enemyEntity, new ChaseComponent { speed = UnityEngine.Random.Range(1f, 3f) });
        }
    }
}

 

3. 추격 시스템 (로직)

using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using UnityEngine;

public class ChaseSystem : SystemBase
{
    protected override void OnUpdate()
    {
        // 플레이어 위치를 가져옵니다. (여기서는 플레이어 GameObject가 있어야 함)
        float3 playerPosition = GameObject.FindWithTag("Player").transform.position;

        // 모든 적 엔티티에 대해 이동 로직 실행
        Entities.ForEach((ref Translation translation, in ChaseComponent chase) =>
        {
            // 적이 플레이어를 향해 이동하는 벡터 계산
            float3 direction = math.normalize(playerPosition - translation.Value);
            translation.Value += direction * chase.speed * Time.DeltaTime;
        }).ScheduleParallel(); // 병렬 처리로 성능 최적화
    }
}

 

재밌다..