Entity Component System
이 기사에 대하여
Entity Component System(이후 ECS)에 대해 설명합니다. 또한 ECS의 C++ 구현EnTT에 대해 소개합니다.
Entity Component System 정보
Entity Component System은 설계 패턴 중 하나입니다. 상속보다 위양을 우선하는 원칙에 따라,
엔티티(게임 장면을 구성하는 적 캐릭터, 문, 총알, etc...)을 부품을 조합하여 구현할 수 있도록 합니다. 이 기술은 긴 상속 관계로 인한 불투명한 구현을 피하고 디자인을 깨끗하게 만듭니다. 반면에 런타임 오버 헤드라는 단점도 있습니다.
ECS는 다음 세 가지 요소로 구성됩니다.
Entity Component System은 설계 패턴 중 하나입니다. 상속보다 위양을 우선하는 원칙에 따라,
엔티티(게임 장면을 구성하는 적 캐릭터, 문, 총알, etc...)을 부품을 조합하여 구현할 수 있도록 합니다. 이 기술은 긴 상속 관계로 인한 불투명한 구현을 피하고 디자인을 깨끗하게 만듭니다. 반면에 런타임 오버 헤드라는 단점도 있습니다.
ECS는 다음 세 가지 요소로 구성됩니다.
컴퍼넌트를 추가하는 컨테이너입니다. 일반적으로 계층 구조를 취합니다. (일반적으로 Entity에는 SubEntity가 있습니다.)
객체의 동작, 외형, 데이터를 정의하는 클래스입니다.
System은 Entity와 Component를 활용하여 데이터를 기반으로 하는 동작과 로직을 유지합니다.
UML로 표현하면 이런 느낌입니다.
Entity에 대해 여러 Component가 연결됩니다.
System은 Entity를 통해 Entity 구성 요소의 Component에 액세스할 수 있습니다. 또, Entity를 개입시키지 않고 모든 Component에 대해서 루프할 수도 있습니다.
ECS는 기존 OOP(객체 지향) 접근법에 비해 다음과 같은 이점이 있습니다.
1. Entity는 포인터가 아닌 ID로 유지할 수 있습니다. 이로 인해 댕글링 포인터 (가리키는 대상이 유효하지 않은 상태에있는 포인터)가 발생하지 않습니다.
2. 외부에 상태를 유지하기 쉬워집니다. 상태를 읽을 때 포인터를 다시 작성할 필요가 없습니다.
3. 메모리의 데이터 위치를 재배치할 수 있습니다.
4. 포인터를 사용하지 않으므로 네트워크를 통해 엔터티를 주고받을 수 있습니다.
해보자! !
위를 읽어보고 ECS에서 놀고 싶어졌다고 생각합니다. C++에서 ECS 구현 EnTT을 사용하여 ECS를 구현해 봅시다.
Sample.cpp#include <entt/entt.hpp>
#include <cstdint>
struct position {
float x;
float y;
};
struct velocity {
float dx;
float dy;
};
// Systemに当たる部分。Entityの位置を更新する。
void update_position(std::uint64_t dt, entt::registry ®istry) {
registry.view<position, velocity>().each([dt](auto &pos, auto &vel) {
// gets all the components of the view at once ...
pos.x += vel.dx * dt;
pos.y += vel.dy * dt;
// ...
});
}
int main() {
entt::registry registry;
std::uint64_t dt = 16;
for(auto i = 0; i < 10; ++i) {
auto entity = registry.create();
registry.assign<position>(entity, i * 1.f, i * 1.f);
if(i % 2 == 0) { registry.assign<velocity>(entity, i * .1f, i * .1f); }
}
update_position(dt, registry);
}
그리고 싶을 때는 새로운 System과 Component를 추가하면 할 수 있습니다.
draw.cppstruct Drawable {
Image image; // 描画に使う画像
};
void update_drawing(entt::registry& registry)
{
registry.view<Drawable, const position>().each([dt](auto &pos, auto &vel) {
// 描画に使うロジック
});
}
참고문헌
#include <entt/entt.hpp>
#include <cstdint>
struct position {
float x;
float y;
};
struct velocity {
float dx;
float dy;
};
// Systemに当たる部分。Entityの位置を更新する。
void update_position(std::uint64_t dt, entt::registry ®istry) {
registry.view<position, velocity>().each([dt](auto &pos, auto &vel) {
// gets all the components of the view at once ...
pos.x += vel.dx * dt;
pos.y += vel.dy * dt;
// ...
});
}
int main() {
entt::registry registry;
std::uint64_t dt = 16;
for(auto i = 0; i < 10; ++i) {
auto entity = registry.create();
registry.assign<position>(entity, i * 1.f, i * 1.f);
if(i % 2 == 0) { registry.assign<velocity>(entity, i * .1f, i * .1f); }
}
update_position(dt, registry);
}
struct Drawable {
Image image; // 描画に使う画像
};
void update_drawing(entt::registry& registry)
{
registry.view<Drawable, const position>().each([dt](auto &pos, auto &vel) {
// 描画に使うロジック
});
}
Reference
이 문제에 관하여(Entity Component System), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/MoriokaReimen/items/e5af3ccdfc740457e721텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)