[UNITY] ECS (Entity Component System) 기본 튜토리얼
- -
ECS - Entity Component System 베이직 튜토리얼 [Best Tips & Tricks by Unity Japan] 이라는 영상을 보고 배운 내용 정리입니다.
프로젝트 설명
3개의 인형이 있습니다.
첫번째 인형은 원형으로 "걷는 인형"
두번째 인형은 좌우로 "춤추는 인형"
세번째 인형은 "걷는 + 춤추는 + 커졌다가 줄어드는 인형" 입니다.
인형별로 차례대로 어떻게 동작하는지에 대해 간략하게 설명하겠습니다.
ECS의 특징으로 각 오브젝트들이 SUB 씬 안에 들어있습니다.
Strawman 이 여기서는 인형이라 칭하겠습니다.
첫번째 인형부터 보시겠습니다.
특징으론 Walker Authoring이라는 스크립트를 제외하고 우리가 아는 다른 오브젝트의 규격처럼 나와있습니다. 또 아래 Entity Baking Preview라는 점이 있다는게 다른점으로 꼽을 수 있겠네요.
Walker Authoring 스크립트
using Unity.Entities;
using UnityEngine;
public struct Walker : IComponentData
{
public float ForwardSpeed;
public float AngularSpeed;
}
public class WalkerAuthoring : MonoBehaviour
{
public float _forwardSpeed = 1;
public float _angularSpeed = 1;
class Baker : Baker<WalkerAuthoring>
{
public override void Bake(WalkerAuthoring src)
{
var data = new Walker()
{
ForwardSpeed = src._forwardSpeed,
AngularSpeed = src._angularSpeed
};
AddComponent(GetEntity(TransformUsageFlags.Dynamic), data);
}
}
}
데이터의 관리는 "public struct 데이터이름 : IcomponentData " 이런식으로 되어있는게 특징이고
기존의 MonoBehaviour에서 베이커를 통해서 베이크를 통해서 엔티티로 만들어 준다는 의미가 다른 점인 것 같습니다.
Baker이란 클래스를 통해서 Bake로 데이터들을 추가해주는 모습이 보입니다.
여기서는 스크립트를 통해 데이터를 다루는 내용이고, 이제 동작하는 System부분을 확인하겠습니다.
System 부분 내용은 그저 스크립트로 만들어두면 자동으로 실행이 됩니다.
여기서 중요한 부분은 클래스부분이 아닌 partial이라고 나와있는데요. 기존 방식과 ecs의 차이라고 할 수 있겠네요.
foreach (var (walker, xform) in
SystemAPI.Query<RefRO<Walker>,
RefRW<LocalTransform>>())
{
var rot = quaternion.RotateY(walker.ValueRO.AngularSpeed * dt);
var fwd = math.mul(rot, xform.ValueRO.Forward());
xform.ValueRW.Position += fwd * walker.ValueRO.ForwardSpeed * dt;
xform.ValueRW.Rotation = quaternion.LookRotation(fwd, xform.ValueRO.Up());
}
이 부분이 핵심내용이라 생각이 드는데
SystemAPI.Query<RefRO<Walker>,
RefRW<LocalTransform>>()
에서 RO 는 ReadOnly, RW 는 ReadWrite 의 약어입니다. 즉 Walker와, LocalTransform이 있는 오브젝트들만 가져와서 실행시켜주는 내역인 것이죠.
첫번째 걷는 인형을 만들기 위해서는
1. 인형 오브젝트를 만든다.
2. Walker Autoring 스크립트로 데이터를 정의한다.
3. System이란 별도의 스크립트들로 각 컴포넌트가 있는 오브젝트를 운영한다. (이때 스크립트들은 어딘가에 붙혀지지않고 그저 폴더에 있습니다.)
라는 방식이 있겠네요.
두번째 춤추는 인형을 빠르게 보자면
1. 오브젝트(엔티티)
2. 데이터 관리 스크립트 (Dancer Authoring) (컴포넌트)
using Unity.Entities;
using UnityEngine;
public struct Dancer : IComponentData
{
public float Speed;
}
public class DancerAuthoring : MonoBehaviour
{
public float _speed = 1;
class Baker : Baker<DancerAuthoring>
{
public override void Bake(DancerAuthoring src)
{
var data = new Dancer(){ Speed = src._speed };
AddComponent(GetEntity(TransformUsageFlags.Dynamic), data);
}
}
}
3. 춤추게 만드는 시스템 스크립트 (Dancer System) (시스템)
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
public partial struct DancerSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
var elapsed = (float)SystemAPI.Time.ElapsedTime;
foreach (var (dancer, xform) in
SystemAPI.Query<RefRO<Dancer>,
RefRW<LocalTransform>>())
{
var t = dancer.ValueRO.Speed * elapsed;
var y = math.abs(math.sin(t)) * 0.1f;
var bank = math.cos(t) * 0.5f;
var fwd = xform.ValueRO.Forward();
var rot = quaternion.AxisAngle(fwd, bank);
var up = math.mul(rot, math.float3(0, 1, 0));
xform.ValueRW.Position.y = y;
xform.ValueRW.Rotation = quaternion.LookRotation(fwd, up);
}
}
}
로 이뤄져있겠네요.
마지막으로 걸으면서 춤추는 인형을 보겠습니다.
1. 오브젝트(엔티티)
2. 컴포넌트
전에 만들어둔 Dancer Authoring, Walker Authoring 스크립트(컴포넌트)를 붙혀둔 상황입니다.
3. 시스템
기존에 만든 DancerSystem, WalkerSystem으로 동작을 잘 하겠지만 여기서 추가적인 기능으로 커졌다가 줄어드는 기능을 넣는 시스템을 만들어 줍니다.
이름은 PulseSystem으로
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
public partial struct PulseSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
var elapsed = (float)SystemAPI.Time.ElapsedTime;
foreach (var (dancer, walker, xform) in
SystemAPI.Query<RefRO<Dancer>,
RefRO<Walker>,
RefRW<LocalTransform>>())
{
var t = dancer.ValueRO.Speed * elapsed;
xform.ValueRW.Scale = 1.1f - 0.3f * math.abs(math.cos(t));
}
}
}
SystemAPI.Query<RefRO<Dancer>,
RefRO<Walker>,
RefRW<LocalTransform>>()
이 코드가 Dancer, Walker, LocalTransform를 동시에 가지고 있는 오브젝트만 커졌다가 줄어들게 해줍니다.
ECS (Entity Component System)이란 유니티 기본의 "객체지향프로그래밍" 에서 엔티티 컴포넌트라는 개발 방법론 에 관련된 내용입니다. 이는 성능 및 확장성을 향상시킬 수 있는 방법론으로 제시되어 왔습니다.
즉 기본 유니티의 구조에서는 게임오브젝트 클래스에 컴포넌트들을 붙혀서 게임의 동작을 만들어가는 것이고, 이 클래스들은 데이터와 처리가 일체화 된 것입니다.
그렇다면 ECS는 어떻게 다를까요?
ecs의 기본 요소는 '엔티티' 로 이루어져있고
데이터를 다루는 컴포넌트들이 붙혀져 있습니다.
그러면서 동작은 System으로 움직이는 셈이죠.
1. Entity(엔터티): 게임 오브젝트를 나타내는 가장 기본적인 단위로, 실제로는 어떠한 동작도 수행하지 않습니다. 대신, 구성 요소들을 가지고 있습니다.
2. Component(컴포넌트): 데이터만을 가지고 있고 로직이 없는 단위로, 엔터티의 특정 부분을 나타냅니다. 예를 들어, 포지션, 로테이션, 모델 등이 될 수 있습니다.
3. System(시스템): 로직이나 동작을 정의하며, 특정 컴포넌트의 데이터를 조작합니다. 시스템은 특정 역할을 수행하기 위해 엔터티 및 컴포넌트의 그룹에 대해 작동합니다.
Ecs는 데이터의 독립성을 매우 높힌 설계라고 합니다.
기존의 객체지향 설계에서는 데이터가 힙 메모리에 산재하는 약점이 있었는데, 너무 무작위적인 메모리 액세스는 대량의 오브젝트를 처리하기에 적합하지 않았습니다.
하지만 Ecs는 데이터는 데이터의 독립성이 높아져서 메모리 접근의 효율성에 초점을 맞춰 정렬 할 수 있습니다. 즉Componet data를 직선으로 쭉 나열 할 수 있습니다.
'💻 Programming (프로그래밍) > Unity | C#' 카테고리의 다른 글
[Unity] 버그 오류 opening project in non-matching editor installation (0) | 2024.03.21 |
---|---|
[Unity][C#][Design Pattern] Strategy pattern - 전략 패턴 (0) | 2023.10.13 |
[Unity][C#][Design pattern] Singleton 기법을 더욱 편리하게 (1) | 2023.10.11 |
[Unity] 새롭게 개정되는 유니티의 가격 정책, 런타임 요금제(0923수정) (0) | 2023.09.19 |
[Unity] 스크립터블 오브젝트(Scriptable Object)로 데이터 저장, 읽기를 손쉽게! (0) | 2023.09.15 |
소중한 공감 감사합니다