엔터티 구성 요소 시스템 아키텍처 개체는 정의 중심입니까?


20

는 IS 엔티티 컴포넌트 시스템 아키텍처의 목적은 정의에 의해, 지향? 좀 더 절차적이고 기능적인 것 같습니다. 내 의견은 그것이 당신이 OO 언어로 그것을 구현하는 것을 방해하지는 않지만, OO 방식으로 그렇게하는 것은 관용적이지 않다는 것입니다.

ECS가 데이터 (E & C)와 동작 (S)을 분리하는 것 같습니다. 증거로 :

아이디어는 엔터티에 게임 방법을 포함시키지 않는 것입니다.

그리고 :

구성 요소는 특정 목적에 필요한 최소한의 데이터 세트로 구성됩니다.

시스템은 특정 구성 요소가있는 엔티티 세트를 취하는 단일 목적 함수입니다.


나는 객체 지향적이기 때문에 데이터와 행동을 함께 결합하기 때문에 이것이 객체 지향이 아니라고 생각합니다. 증거로 :

반대로, 객체 지향 접근 방식은 프로그래머가 나머지 프로그램에서 직접 액세스 할 수없는 위치에 데이터를 배치하도록 권장합니다. 대신 데이터와 함께 번들로 제공되는 일반적으로 메소드라고하는 특수하게 작성된 함수를 호출하여 데이터에 액세스합니다.

반면에 ECS는 행동과 데이터를 분리하는 것입니다.

답변:


21

소개


엔터티 구성 요소 시스템은 객체 지향 아키텍처 기술입니다.

객체 지향 프로그래밍과 마찬가지로이 용어의 의미에 대한 보편적 인 합의는 없습니다. 그러나 엔터티 구성 요소 시스템은 상속에 대한 아키텍처 대안으로 특별히 의도 된 것 입니다. 상속 계층은 객체 무엇인지를 표현하는 데 자연 스럽지만 특정 종류의 소프트웨어 (예 : 게임)에서는 객체 하는 것을 표현하는 것이 좋습니다.

C ++ 또는 Java 작업에 익숙한 "클래스 및 상속"모델과 다른 객체 모델입니다. 엔터티는 JavaScript 또는 자체에서와 같이 프로토 타입과 마찬가지로 클래스만큼 표현력이 뛰어납니다. 이러한 모든 시스템은 서로의 관점에서 구현 될 수 있습니다.

 


하자 말 Player과 실체 Position, Velocity그리고 KeyboardControlled뻔한 일을 할 구성 요소.

entity Player:
  Position
  Velocity
  KeyboardControlled

우리는 알고 Position에 의해 영향을해야 Velocity하고, Velocity에 의해 KeyboardControlled. 문제는 이러한 효과를 어떻게 모델링하고 싶은가입니다.

 

엔터티, 구성 요소 및 시스템


구성 요소가 서로를 참조하지 않는다고 가정하십시오. 외부 Physics시스템은 모든 Velocity구성 요소를 통과 Position하고 해당 엔티티를 업데이트합니다 . Input시스템은 모든 횡단 KeyboardControlled구성 요소와를 업데이트합니다 Velocity.

          Player
         +--------------------+
         | Position           | \
         |                    |  Physics
       / | Velocity           | /
  Input  |                    |
       \ | KeyboardControlled |
         +--------------------+

이는 다음 기준을 충족시킵니다.

  • 게임 / 비즈니스 로직은 개체에 의해 표현되지 않습니다.

  • 컴포넌트는 동작을 설명하는 데이터를 저장합니다.

시스템은 이제 이벤트를 처리 하고 구성 요소가 설명하는 동작을 제정 합니다. 또한 충돌과 같은 엔터티 간 상호 작용을 처리합니다.

 

엔터티 및 구성 요소


그러나 구성 요소가 있다고 가정 서로에 대한 참조를 가지고있다. 이제 엔티티는 단순히 일부 구성 요소를 작성하고 함께 바인딩하며 수명을 관리하는 생성자입니다.

class Player:
  construct():
    this.p = Position()
    this.v = Velocity(this.p)
    this.c = KeyboardControlled(this.v)

엔티티는 이제 입력 및 업데이트 이벤트를 해당 컴포넌트로 직접 전달할 수 있습니다. Velocity업데이트에 KeyboardControlled응답하고 입력에 응답합니다. 이것은 여전히 ​​우리의 기준을 충족시킵니다.

  • 이 엔터티는 이벤트를 구성 요소에만 전달하는 "dumb"컨테이너입니다.

  • 각 구성 요소는 자체 동작을 수행합니다.

여기서 컴포넌트 상호 작용은 시스템에 의해 외부에서 부과되지 않고 명시 적입니다. 행동을 설명하는 데이터 (속도의 양은 얼마입니까?)와이를 실행하는 코드 (속도는 무엇입니까?)는 자연스럽게 결합되어 있습니다. 데이터는 동작에 대한 매개 변수로 볼 수 있습니다. 그리고 일부 구성 요소는 전혀 작동하지 않습니다 . 즉, 제자리에있는Position 동작입니다 .

상호 작용은 실체 수준 ( " … Player과 충돌 할 때 Enemy") 또는 개별 구성 요소 수준 ( " … Life과 실체와 충돌 할 때 Strength")에서 처리 될 수있다.

 

구성 요소


실체가 존재하는 이유는 무엇입니까? 단순한 생성자 인 경우 구성 요소 집합 을 반환하는 함수로 대체 할 수 있습니다 . 나중에 유형별로 엔터티를 쿼리하려는 경우 다음과 같이 할 수있는 Tag구성 요소를 가질 수도 있습니다 .

function Player():
  t = Tag("Player")
  p = Position()
  v = Velocity(p)
  c = KeyboardControlled(v)
  return {t, p, v, c}
  • 엔티티는 가능한 한 바보입니다. 단지 컴포넌트 세트 일뿐입니다.

  • 구성 요소는 이전과 같이 이벤트에 직접 응답합니다.

상호 작용 이제 추상 쿼리에 의해 처리되어 엔티티 유형에서 이벤트를 완전히 분리합니다. 쿼리 엔티티 유형 이 더 이상 없습니다Tag . 게임 논리보다 임의의 데이터가 디버깅에 더 적합 할 것입니다.

 

결론


엔터티는 함수, 규칙, 행위자 또는 데이터 흐름 결합자가 아닙니다. 그것들은 구체적인 현상을 모델로 하는 명사 , 즉 객체입니다. 엔터티 구성 요소 시스템은 일반 개체를 모델링하기위한 소프트웨어 아키텍처 패턴입니다.


2
클래스 기반 OO, 프로토 타입 기반 OO의 주요 대안은 데이터와 동작을 결합한 것으로 보입니다. 실제로 클래스 기반 OO와 마찬가지로 ECS와는 다른 것 같습니다. OO의 의미를 자세히 설명해 주시겠습니까?

@delnan의 질문에 덧붙이려면 인용 한 OO wikipedia 기사의 스 니펫에 동의하지 않습니까?
Daniel Kaplan

@tieTYT : Wikipedia 인용문은 캡슐화와 정보 숨기기에 대해 이야기하고 있습니다. 데이터-행동 커플 링이 필요하다는 증거는 아니라고 생각합니다.
Jon Purdy

@ delnan : OO의 의미는 없습니다. 의 특정 정의 (기능, 규칙, 배우, 흐름 콤비 등 반대) "객체"로 프로그래밍 : 객체 지향 프로그래밍, 나에게, 그것은 주석에 말한다 정확히 객체가 구현 정의이다.
Jon Purdy

1
@tieTYT : 필자는 Wikipedia 설명과 모순되지는 않지만 광범위하게 광범위하다는 용어를 전달하기 위해 야생에서 본 구현을 설명했습니다.
Jon Purdy

20

아니. 그리고 얼마나 많은 사람들이 다른 투표를했는지 놀랍습니다!

어형 변화표

그것은의 데이터가 지향 일명 데이터 기반 우리가 얘기하고 있기 때문에 구조 가 아닌 언어 가로 작성. 아키텍처는 스타일 또는 프로그램의 실현입니다 패러다임 보통 unadvisably 주어진 언어로 해결할 수 있습니다.


기능의?

에 대한 귀하의 비교 기능 / 절차 적 프로그래밍은 적절하고 의미있는 비교입니다. 그러나 "기능" 언어 는 "절차" 패러다임 과 다릅니다 . 또한 사람들이 수행 한 Haskell 과 같은 기능적 언어로 ECS를 구현할 수 있습니다 .


응집력이 발생하는 곳

귀하의 관찰은 관련성이 있고 현장에 있습니다 .

"... [ECS]가 OO 언어로 구현하는 것을 방해하지는 않지만 OO 방식으로 그렇게하는 것은 관용적이지 않습니다."


ECS / ES가 EC / CE가 아님

구성 요소 기반 아키텍처 인 "Entity-Component"와 "Entity-Component-System"에는 차이가 있습니다. 이것이 진화하는 디자인 패턴이기 때문에 이러한 정의가 상호 교환 적으로 사용되는 것을 보았습니다. "EC"또는 "CE"또는 "Entity-Component"아키텍처 구성 요소 에 동작을 배치 하는 반면 "ES"또는 "ECS"아키텍처 는 시스템에 동작을 적용합니다 . 다음은 몇 가지 ECS 기사로, 잘못된 명명법을 사용하지만 일반적인 아이디어를 얻습니다.

2015 년에 이러한 용어를 이해하려는 경우 "엔터티 구성 요소 시스템"에 대한 누군가의 참조가 "엔터티 구성 요소 아키텍처"를 의미하지 않아야합니다.


1
이것이 정답입니다. ECS는 OOP 패러다임과 잘 맞지 않습니다. ECS는 데이터와 동작을 분리하는 것이지만 OOP는 그 반대입니다.
Nax 'vi-vim-nvim'5

"OOP는 정반대 인 반면"실제로는 결코 사용되지 않는 SmallTalk와 같은 쓸데없는 학문적 정의가 없다면 OOP에 대한 정의는 받아 들여지지 않습니다.
Jean-Michaël Celerier

10

엔터티 구성 요소 시스템 (ECS)은 시스템 정의 방법에 따라 OOP 또는 기능 방식으로 프로그래밍 할 수 있습니다.

OOP 방식 :

엔터티가 다양한 구성 요소로 구성된 개체 인 게임에서 작업했습니다. 엔터티에는 모든 구성 요소에서 업데이트를 차례로 호출하여 개체를 수정하는 업데이트 기능이 있습니다. 이것은 스타일에서 분명히 OOP입니다. 동작은 데이터에 연결되며 데이터는 변경 가능합니다. 엔터티는 생성자 / 소멸자 / 업데이트가있는 개체입니다.

더 기능적인 방법 :

대안은 엔티티가 메소드없이 데이터가되는 것입니다. 이 엔티티는 그 자체로 존재하거나 단순히 다양한 구성 요소에 연결된 ID 일 수 있습니다. 이러한 방식으로 (그러나 일반적으로 수행되지는 않지만) 완벽하게 기능하고 새로운 구성 요소 상태를 생성하는 불변의 엔티티 및 순수한 시스템을 가질 수 있습니다.

후자의 방법은 (개인 경험에서) 더 많은 견인력을 얻고 있으며 좋은 이유가있는 것 같습니다. 엔티티 데이터와 동작을 분리하면 더 유연하고 재사용 가능한 코드 (imo)가됩니다. 특히 시스템을 사용하여 구성 요소 / 엔터티를 일괄 업데이트하면 성능이 향상 될 수 있으며 많은 OOP ECS를 괴롭히는 엔터티 간 메시징의 복잡성을 완전히 피할 수 있습니다.

TLDR : 어느 쪽이든 할 수 있지만, 좋은 엔터티 구성 요소 시스템의 이점은 더 많은 기능적 특성에서 비롯된다고 주장합니다.


구성 요소의 전체 요점 때문에 특히 더 많은 견인력은 다루기 힘든 OOP 계층 구조에서 벗어나는 이점이있었습니다.
Patrick Hughes

2

데이터 지향 엔터티 구성 요소 시스템은 객체 지향 패러다임과 공존 할 수 있습니다.-구성 요소 시스템은 다형성에 적합합니다. -컴포넌트는 POD (일반 데이터) 및 ALSO 오브젝트 (클래스 및 메소드 포함) 일 수 있으며 컴포넌트 클래스 메소드가 로컬 오브젝트가 소유 한 데이터 만 조작 할 경우 모든 것이 여전히 '데이터 지향적'입니다.

이 경로를 선택하면 가상 메서드를 사용하지 않는 것이 좋습니다. 가상 메서드가있는 경우 구성 요소는 더 이상 순수하게 구성 요소 데이터가 아니고 해당 메서드를 호출하는 데 비용이 많이 들며 이는 COM이 아닙니다. 컴포넌트 클래스는 일반적으로 외부에 대한 참조를 깨끗하게 유지하십시오.

예를 들어 vec2 또는 vec3, 해당 데이터를 터치하는 몇 가지 방법이있는 데이터 컨테이너 등이 있습니다.


2
이 게시물은 읽기 어렵습니다 (텍스트의 벽). 더 나은 형태로 편집 하시겠습니까 ? 또한 독자들에게 링크 된 블로그 기사가 유용하고 질문 된 질문과 관련이있는 이유를 설명하는 데 도움이 될 것입니다.
gnat

... 어떻게 든 당신이 그 블로그와 관련이 있다면 (당신이 있습니까?) 제휴
gnat

예, 저의 블로그입니다. 저는 공개 블로그와 밀접하게 연계되어 있으며 데이터 지향 디자인 원칙을 기반으로 객체 지향 엔티티 구성 요소 시스템의 세부 정보를 공개합니다. 관련성이 있고 유용하다고 생각합니다. 편견을 제거하십시오.
호머

2

ECS는 OOP와 근본적으로 구별되는 것으로 생각하며 기능과 데이터가 매우 뚜렷하게 구분되어 기능적 또는 특히 절차 적 특성에 더 가깝게 접근하는 것과 동일한 방식으로 보는 경향이 있습니다. 중앙 데이터베이스를 다루는 종류의 프로그래밍과 약간의 유사성이 있습니다. 물론 공식적인 정의에 관해서는 최악의 사람입니다. 나는 개념적으로 정의 된 것이 아니라 상황이 어떤지에 대해서만 관심이 있습니다.

구성 요소가 데이터 필드를 집계하고 공개적으로 / 전 세계적으로 액세스 가능하게하고, 개체를 집계하고, 시스템이 해당 데이터에 대한 기능 / 동작을 제공하는 일종의 ECS를 가정합니다. 그것은 우리가 일반적으로 객체 지향 코드베이스라고 부르는 것에서 근본적으로 어려운 구조적 특성으로 이어집니다.

물론 사람들이 ECS를 설계 / 구현하는 방식에는 경계가 흐려지고, 우선 ECS를 정확히 구성하는 요소에 대한 논쟁이 있습니다. 그러나 이러한 경계는 우리가 기능적 또는 절차 적 언어라고 부르는 코드로 흐리게 표시됩니다. 이러한 모든 모호함 중에서 기능과 데이터를 분리 한 ECS의 기본 상수는 OOP보다 나에게 기능 또는 절차 적 프로그래밍에 훨씬 더 가깝습니다.

ECS가 OOP 클래스에 속한다고 생각하는 것이 도움이되지 않는 주된 이유 중 하나는 OOP와 관련된 SE 관행 대부분이 데이터가 아닌 공용 인터페이스 모델링 기능을 사용 하여 공용 인터페이스 안정성을 중심으로 하기 때문입니다. 기본 아이디어는 대부분의 공공 의존성이 구체적인 데이터가 아닌 추상 기능으로 흘러가는 것입니다. 그 때문에 OOP는 기본 설계 동작을 변경하는 데 비용이 많이 드는 반면, 구체적인 세부 사항 (기능을 구현하는 데 필요한 데이터 및 코드 등)을 변경하는 것은 매우 저렴합니다.

ECS는 대중의 의존성이 시스템에서 구성 요소에 이르기까지 구체적인 데이터를 향해 흐를 때 사물이 어떻게 결합되는지를 고려하면 근본적으로 다릅니다. 결과적으로 ECS와 관련된 모든 SE 관행은 데이터 안정성 과 관련이 있습니다 . 가장 널리 사용되고 널리 사용되는 인터페이스 (구성 요소)는 실제로 데이터 일뿐입니다.

결과적으로 ECS는 DX와 GL 엔진을 모두 제공하는 두 가지가 완전히 다른 기능으로 구현되고 동일한 디자인을 공유하지 않더라도 DirectX를 OpenGL 렌더링 엔진으로 대체하는 것과 같은 일을 매우 쉽게 수행 할 수 있습니다. 동일한 안정적인 데이터에 액세스 할 수 있습니다. 한편, 그것은 매우 비싸고, 데이터 표현을 변경하기 위해 많은 시스템을 재 작성해야한다 MotionComponent.

이는 적어도 결합 특성과 "공개 인터페이스"와 "개인 구현 세부 사항"의 관점에서 OOP와 전통적으로 연관되는 것과는 정반대입니다. 물론 두 경우 모두 "구현 세부 사항"은 변경하기 쉽지만 ECS에서는 변경 비용이 많이 드는 데이터 디자인 (ECS에서는 데이터가 구현 세부 사항이 아님)이고 OOP에서는 변경 비용이 많이 드는 기능 설계입니다. (함수 디자인은 OOP의 구현 세부 사항이 아닙니다). 그것은 "구현 세부 사항"에 대한 매우 다른 생각이며, 유지 관리 관점에서 ECS에 대한 주요 호소 중 하나는 내 영역에서 작업을 수행하는 데 필요한 데이터는 해당 데이터로 수행 할 수있는 모든 다양한 작업 (클라이언트가 마음을 바꾸고 새로운 사용자 제안이 쏟아져 나올 때마다 항상 변경됨)보다 한 번에 정확하게 안정화하고 디자인하기가 더 쉬웠습니다. 결과적으로 의존성을 추상 함수에서 원시 중앙 데이터로 향하게하기 시작했을 때 유지 보수 비용이 급감했습니다 (그러나 여전히 모든 데이터가 개념적으로 있음에도 불구하고 어떤 시스템이 어떤 구성 요소에 액세스하여 불변량을 제정신 수준으로 유지할 수 있는지주의하면서) 전 세계적으로 액세스 가능).

필자의 경우 적어도 API가 포함 된 ECS SDK 및 모든 구성 요소는 실제로 C로 구현되며 OOP와 유사하지 않습니다. ECS 아키텍처에서 OO가 본질적으로 부족 하고 가장 광범위한 언어와 컴파일러에서 사용할 수있는 플러그인 아키텍처를 원한다는 에서 C가 그러한 목적에 적합하다는 것을 알았습니다 . C ++로 인해 시스템이 매우 편리하고 시스템이 복잡성을 모델링하기 때문에 시스템은 여전히 ​​C ++로 구현되며 OOP에 더 가깝게 고려 될 수 있지만 많은 구현에 사용됩니다. 건축 디자인 자체는 여전히 매우 절차적인 C와 유사합니다.

따라서 ECS가 정의에 따라 OO라고 말하는 것이 적어도 혼란 스럽다고 생각합니다. 최소한 기본은 캡슐화로 시작하여 원하는 커플 링 특성으로 간주되는 것으로 끝나는 OOP와 일반적으로 관련된 많은 기본 원칙에서 완전히 180도 회전하는 작업을 수행합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.