참고
https://github.com/SanderMertens/ecs-faq?tab=readme-ov-file
ECS에 대한 기본 지식
ECS는 OOP와 어떻게 다른가?
- OOP에서 가장 중요한 것은 Inheritance(상속)인 반면, ECS에서 가장 중요한 것은 Composiotion(구성)이다.
- OOP는 데이터의 캡슐화를 추구하고 ECS는 POD(plain old data) 객체를 보여주는 것을 추구한다.
- OOP는 behavior와 함께 데이터를 같이 두는 것을 중시하고 ECS는 behavior로부터 데이터를 분리하는 것을 중시한다.
- OOP 객체 인스턴스는 단일 정적 타입이지만, ECS의 entities는 다중 타입을 가지며, dynamic하게 변화하는 components를 가질 수 있다.
ECS와 Entity-Component Frameworks의 차이
ECS와 EC 프레임워크는 다르다. EC 프레임워크는 게임엔진에서 전형저그올 발견된다. ECS와 EC프레임워크는 Entity를 만드는 것과 Components의 구성이 유사하다는 점이 있다.
하지만, EC 프레임워크는 components가 data와 behavior이 같이 포함된 클래스로 되어있다. 그리고 component에서 직접적으로 실행된다.
대표적인 예시로, 유니티의 GameObject
System과 유사하다.
// Simple EC framework
class IComponent {
public:
virtual void update() = 0;
};
class Entity {
vector<IComponent*> components;
public:
void addComponent(IComponent *component);
void removeComponent(IComponent *component);
void updateComponents();
};
자신만의 ECS를 작성해야 하는가?
ECS의 컨셉과 규칙은 어렵지 않기 때문에 ECS를 설계하는 것은 어렵지 않다. 자신만의 ECS를 만들면 주는 이점이 많이 있으므로 때로는 설계하는 것이 필요하다.
ECS를 어떻게 디자인해야 하는가?
- 얼마나 인스턴스 데이터를 만들 것인가
- 얼마나 data에 종종 access할 것인가
- 얼마나 data가 종종 mutated(변경)되는가
- 얼마나 data가 access/muate가 필요한가
- data의 cardinality는 무엇인가?
- cardinality : 데이터 모델링에서 한 테이블이 다른 테이블과 가질 수 있는 관계를 의미한다. (e.g. 다대다/일대다)
- 중복도가 '낮으면' cardinality가 '높다'라고 표현
- 중복도가 '높으면' cardinality가 '낮다'라고 표현
implemented ECS의 종류는 어떻게 되는가?\
- Archetypes(aka "Dense ECS" or "Table based ECS")
- table에 entites를 저장하는 ECS이다.
- col은 components이며 row는 entities가 된다.
- Spares set ECS (aka "Sparse ECS")
- 자신의 entitiy id를 가지는 sparse set에 각 component를 저장한다.
- sparse set 구현을 통해 추가와 삭제 동작을 빠르게 구현할 수 있다.
- Bitset based ECS
- entity id를 index로써 사용하는 array에 component를 저장한다.
- 특정 entity에 특정한 component에 접근하기 위해서 bitset을 이용한다.
- Reactive ECS
- entity mutations으로 부터 반환되는 signals을 사용한다.
entities를 시스템과 어떻게 매치시키냐?
- Archetype-based ECS 기반은 테이블의 형태로 저장하게 된다. 이 접근은 테이블이 빠르게 안정화되므로, 오버헤드가 0에 가깝게 줄어든다는 이점이 있다.
- Sparse Set ECS는 하나의 명령된 components를 위해 모든 entities를 반복한다. 그리고 만약 특정 entity가 그것을 가지고 있다면, component의 구성 요소를 검사한다. 이러한 접근 방식은 Bitset-based ECS와 유사하다.
Entity Relationships는 무엇인가
Entity Relationships는 ECS 모델의 확장 기능이다.
alice.add<Likes>(bob);
예제에서 "Likes, bob" 은 pair이다. "Likes"는 relationship의 한 종류이고 "bob"은 relationship target이다. "alice"와 "bob"은 entities이다.
ECS에서 계층구조를 어떻게 만드는가?
ECS에서 계층을 구현하는 것은 몇가지 방법이 존재한다. 그리고 이것은 ECS implementation에 의존하게 된다.
// Store the parent entity on child entities
struct Parent {
entity parent;
};
// Store all children of a parent in a component with a vector
struct Children {
vector<entity> children;
};
// Store children in linked list
struct ChildList {
entity first_child; // First child of entity
entity prev_sibling; // Previous sibling
entity next_sibling; // Next sibling
};
이 접근의 단점은 component 조회에 의존한다는 점이다. 그리고 이것은 시스템을 느리게 만들 수 있다. 유연하기는 하지만, low-level 시스템에 적용하는 것은 이상적이지 않다.
계층을 top-down식(양이 많은 친구는 뒤로)으로 만들어 entities를 sorting해서 계층구조를 접근하는 방법이 있다. 다만, 이 방법은 너무 자주 sorting 해야한다는 단점이 있다.
Archetype-based ECS는 여러 테이블에 걸쳐 하위 트리로 분리하는 것을 허용한다. tabel/subtree는 가지고 있는 depth에 의해 sorting된다. 이것은 Iteration이 빠르고 sorting이 빈번하지 않다는 장점이 있다. 다만, 이 접근은 성능을 저하시킬 수 있는 많은 small tables를 만든다는 단점이 있다.
ECS에서는 spatial data(공간 데이터)를 어떻게 저장하는가
Spatial data는 quadtree나 octress와 같은 구조를 가지고 있다. 이러한 구조는 직접적으로 저장되지 않는다. 전형적으로 ECS layout과 맞지 않기 때문이다.
One approach that works well for narrow-phase spatial queries in combination with an ECS is to create a query that iterates relevant entities and stores them in a spatial structure at the beginning (or end) of each frame.
For broad-phase spatial queries an application could leverage runtime tags (if the ECS supports it) where a tag corresponds with a cell in a spatial grid. Combined with queries that match the tag, an application can quickly discard large groups of entities that are not in a certain area.
'Riley-Engine' 카테고리의 다른 글
AABB에 대해서 (0) | 2024.07.30 |
---|---|
bug : camera의 Projection 행렬 값 오류 (0) | 2024.07.24 |
bug : Shadow mapping 그림자 관련 (2) | 2024.07.24 |
bug : ResizeBuffers() 가 정상작동하지 않는 문제. (0) | 2024.07.17 |
bug : Shader stage did not run (0) | 2024.07.17 |