엔터티 구성 요소 시스템에서 "Blob-Systems"를 피하는 방법은 무엇입니까?


10

현재 다음 문제에 직면하고 있습니다.

엔터티 구성 요소 시스템 (ECS) 을 사용하여 퐁 클론을 작성하려고합니다 . 나는 스스로 "프레임 워크"를 썼습니다. 따라서 모든 구성 요소로 엔티티를 관리하는 클래스가 있습니다. 그런 다음 구성 요소 클래스 자체가 있습니다. 마지막으로 시스템에 필요한 구성 요소가있는 모든 엔티티를 얻는 시스템이 있습니다.

예를 들어 내 이동 시스템은 위치 구성 요소와 이동 구성 요소가있는 모든 엔티티를 찾습니다. 위치 구성 요소는 위치를 유지하고 이동 구성 요소는 속도를 유지합니다.

그러나 실제 문제는 내 충돌 시스템입니다. 이 클래스는 논리적 얼룩과 같습니다. 이 수업에는 특별한 경우가 많이 있습니다.

예를 들어 : 내 패들이 테두리와 충돌 할 수 있습니다. 이 경우 속도가 0으로 설정됩니다. 내 공은 테두리와 충돌 할 수 있습니다. 그러나이 경우 속도는 경계의 법선에서 미러링되므로 반영됩니다. 이것을하기 위해 공에 여분의 물리 성분을주었습니다. "이건 멈추지 않고 반영합니다." 실제로 물리 구성 요소에는 실제 데이터가 없습니다. 객체가 반영되거나 중지되는지를 시스템에 알리기 위해 빈 클래스입니다.

공이 패 들이나 경계와 충돌 할 때 입자를 렌더링하고 싶습니다. 공은 충돌시 파티클을 생성하도록 충돌 시스템에 지시하는 다른 구성 요소를 가져와야한다고 생각합니다.
그런 다음 패들과 충돌 할 수 있지만 국경과는 충돌 할 수있는 파워 업을 원합니다. 이 경우 파워 업이 사라져야합니다. 따라서 더 많은 케이스와 구성 요소가 필요합니다 (일부 엔티티가 특정 엔티티와 충돌 할 수 있음을 시스템에 알리려면 일부는 실제로 충돌 할 수는 있지만 충돌 시스템은 파워 업을 적용해야했습니다) 패들 등 등).

엔터티 구성 요소 시스템은 유연하고 상속에 문제가 없기 때문에 좋은 것입니다. 그러나 나는 현재 완전히 붙어 있습니다.

너무 복잡하다고 생각합니까? 이 문제에 어떻게 대처해야합니까?

물론, 실제로 "포스트 콜리 전"을 담당하는 시스템을 만들어야하므로 콜리 전 시스템은 "예, 마지막 프레임에 충돌이 있습니다"라는 메시지 만 표시하고 "포스트 콜리 전"시스템이 많이 있습니다. 모두 서로 다른 (조합) 구성 요소가 필요하며 구성 요소를 변경하십시오. 예를 들어 충돌 후 충돌을 멈추는 동작을 중지시키는 이동 후 충돌 시스템이 있습니다. 그런 다음 사물 등을 반영하는 물리 사후 충돌 시스템

그러나 이것은 나에게 적절한 해결책이 아닌 것 같습니다.

  1. 내 충돌 사후 충돌 시스템에는 위치 구성 요소, 이동 구성 요소 및 충돌 구성 요소가있는 엔티티가 필요합니다. 그런 다음 엔터티의 속도를 0으로 설정합니다.
  2. 물리 후 충돌 시스템에는 위치 구성 요소, 이동 구성 요소, 충돌 구성 요소 및 물리 구성 요소가있는 엔티티가 필요합니다. 그런 다음 속도 벡터를 반영합니다.

문제는 명백합니다. 충돌 후 이동은 물리 후 충돌 시스템에서 엔티티의 하위 집합 인 엔티티가 필요합니다. 따라서 두 개의 충돌 후 시스템이 동일한 데이터에서 작동하며 그 결과는 다음과 같습니다. 엔티티에는 물리 구성 요소가 있지만 충돌 후 속도는 0입니다.

엔터티 구성 요소 시스템에서 이러한 문제는 일반적으로 어떻게 해결됩니까? 그 문제가 평소에도 있습니까 아니면 내가 잘못하고 있습니까? 그렇다면 무엇을 어떻게해야합니까?

답변:


11

예, 당신은 너무 복잡하다고 생각합니다.

메시징 시스템 과 일부 필터 를 지정할 수있는 추가 속성 으로 많은 문제를 해결할 수있는 것처럼 들리 며 결국 엔터티 / 구성 요소에 대해 엄격하게 걱정하지 않아도됩니다.

메시지는 파티클 트리거, 파워 업 등과 같은 일부 측면에서 도움이됩니다. 예를 들어 파티클 이벤트를 구독하고 이벤트에 설명 된 위치에 파티클을 생성하는 월드 객체를 가질 수 있습니다.

필터는 충돌에 많은 도움이됩니다. 필터는 객체가 다른 객체와 충돌하는지와 어떤 응답을 가질 지 정의 할 수 있습니다. 어떤 유형의 물리 바디, 충돌하는 다른 유형의 물리 바디 및 응답을 정의하는 몇 가지 속성을 물리 컴포넌트에 추가합니다. 예를 들어, 공 물리 객체는 패들 물리 객체와 충돌하여 반사 및 입자로 반응합니다.

마지막으로 구현에 대해 너무 엄격하지 마십시오. 작동시키는 방법을 찾을 수 있지만 실제로 EC 시스템이 아닌 경우 수행하십시오. 위의 예에서와 같이 파티클은 시스템이나 EC 시스템의 일부로 전혀 관리 할 필요가 없습니다. 이미 잘 정의되지 않은 방법을 엄격하게 따르는 것보다 게임을 끝내는 것이 더 중요합니다.


대단히 감사합니다. ECS를 사용하여 게임이 어떻게 확장되는지, 기사와 자습서를 읽을 때 사용하기에 정말 좋은지 살펴보고 싶었습니다. 내 문제는 내가 생각하기에 "지금 ECS가 있고 모든 것이 이것에 의해 관리되어야합니다." 그래서 ECS와 관련하여 파티클 시스템을 작성하려고 계획했습니다. 또한 일부 기사에서는 모든 구성 요소에 기본 데이터가 있어야하며 더 이상 아무것도 없어야한다는 기사를 읽었습니다. 그것은 종종 내 문제입니다 ... 너무 복잡하다고 생각합니다.
M0rgenstern 2016 년

ECS를 사용하여 게임이 어떻게 확장되는지, 기사와 튜토리얼에서 읽을 때 사용하기에 정말 좋은지 살펴보고 싶었습니다 . 그것이 당신의 목표라면, 당신은 당신의 시스템을 구축하는 대신에 기존의 컴포넌트 / 엔티티 시스템을 보는 것이 좋습니다. 아마도 "순수한 구성 요소"일 수도있는 Unity3D를 다운로드하여 플레이하십시오. 훨씬 빠른 통찰력, IMHO.
Imi

3
@lmi : Unity는 컴포넌트 기반이지만 엔티티 컴포넌트 시스템이 아닙니다. ECS에는 단순히 게임 오브젝트 구성 요소를 사용하고 사용 하는 것보다 다소 엄격한 지침 ( 패턴을 규칙으로 생각 하지 않음 )이 있습니다. 일련의 기사로 인해 ECS는 현재 일부 게임 개발자들에게 인기가 있으므로 일반적으로 구성 요소 기반 디자인보다는 ECS에 대한 많은 질문이 있습니다.
Sean Middleditch 2016 년

12

당신은 너무 복잡합니다. 구성 요소 기반 디자인을 사용하는 것조차도 단순한 게임에는 너무 과잉이라고 말할 수 있습니다. 게임을 빠르고 쉽게 개발할 수있는 방식으로 작업하십시오. 구성 요소는 다양한 동작과 게임 개체 구성을 사용하여 대규모 프로젝트에서 반복 작업을 수행하는 데 도움이되지만 이러한 간단하고 정의 된 게임에 대한 이점은 더 의심됩니다. 작년에 이것에 대해 이야기를 나 architecture습니다 . 아키텍처고수하는 대신 게임만드는 데 집중하면 몇 시간 만에 재미있는 작은 게임을 만들 수 있습니다 . 100 개 또는 20 개의 서로 다른 유형의 객체가 있으면 상속이 무너지지 만 소수만 있으면 제대로 작동합니다.

학습 목적으로 구성 요소를 계속 사용한다고 가정하면 접근 방식에 눈에 띄는 몇 가지 명백한 문제가 있습니다.

먼저 구성 요소를 너무 작게 만들지 마십시오. '움직임'과 같이 세분화 된 구성 요소를 가질 이유가 없습니다. 게임에는 일반적인 움직임이 없습니다. 패들에는 움직임이 입력 또는 AI와 밀접하게 연결되어 있으며 (실제로 속도, 가속도, 회복 등을 사용하지 않음) 공이 있으며 잘 정의 된 움직임 알고리즘이 있습니다. PaddleController 구성 요소와 BouncingBall 구성 요소 또는 그 선을 따라 뭔가가 있습니다. 더 복잡한 게임을 얻는 경우 더 일반적인 PhysicsBody 구성 요소 ( '실제'엔진에서는 기본적으로 게임 객체와 Havok / PhysX / Bullet / 다양한 상황을 처리하는 Box2D 등).

'포지션'구성 요소조차 의심의 여지가 없지만 의문입니다. 물리 엔진은 일반적으로 객체의 위치, 그래픽에 보간 된 표현, AI가 다른 상태의 동일한 데이터에 대한 또 다른 표현을 가질 수 있다는 내부 아이디어를 가지고 있습니다. 각 시스템이 시스템 자체 구성 요소의 변환에 대한 자체 아이디어를 관리하게하고 시스템간에 원활한 통신이 이루어 지도록하는 것이 유리할 수 있습니다. 이벤트 스트림에 관한 BitSquid 블로그 게시물을 참조하십시오 .

맞춤형 물리 엔진의 경우 구성 요소에 대한 데이터를 보유 할 수 있습니다. 어쩌면 일반적인 Pong 물리 구성 요소에는 이동할 수있는 축을 나타내는 데이터가 있습니다 (예 : vec2(0,1)Y 축에서만 이동할 수있는 패들과 vec2(1,1)이동할 수 있음을 나타내는 공의 경우 승수 ). 공은 일반적으로 있고 1.0패들0.0), 가속도 특성, 속도 등입니다. 이를 고도로 관련된 데이터의 각 부분에 대해 다양한 마이크로 구성 요소로 나누려고 시도하는 것은 ECS가 원래 의도했던 것과 반대됩니다. 가능한 한 동일한 구성 요소에 함께 사용되는 것을 유지하고 각 게임 개체가 해당 데이터를 사용하는 방법에 큰 차이가있을 때만 분할하십시오. Pong의 경우 볼과 패들 사이의 물리학이 별도의 구성 요소가 될만큼 충분히 다르다는 주장이 있지만 더 큰 게임의 경우 20에서 구성 요소를 1-3에서 올바르게 작동하도록 만들 이유가 거의 없습니다.

ECS 버전이 방해를 받으면 실제로 게임을하고 디자인 패턴 / 아키텍처에 대한 철저한 준수를 잊어 버리는 데 필요한 것을 수행하십시오.


1
정말 고마워! ECS는 탁구와 같은 작은 게임에 적합하지 않습니다. 그러나 나는 그런 것들이 실제로 어떻게 구현되고 어떻게 작동하는지 알기 위해 그것을 사용했습니다. 구성 요소를 너무 작게 만들었습니다. 일부 기사에서 주로 읽었 기 때문입니다. 많은 구성 요소가 있고 각 구성 요소는 기본 데이터 만 보유합니다. 따라서 상속과 ECS를 혼합하여 사용하는 것이 좋습니다. 당신이 말하는 것처럼 "공과 패들은 서로 다른 구성 요소가 될만큼 충분히 다릅니다". 예를 들어, 나는 그들에게 Movement / Position 컴포넌트 (하나의 컴포넌트 일 수도 있음)와
M0rgenstern

1
뭐든간에 게임 제작에 집중하십시오. 말 그대로 Ball운동, 튀는 등 공에 대한 모든 논리를 포함하는 Paddle구성 요소 와 입력을 받는 구성 요소가 있지만 그게 나입니다. 당신에게 가장 합리적이고 당신의 길에서 벗어나 게임을 할 수있게하는 것은 일을하는 "올바른 방법"입니다.
Sean Middleditch 2016 년

3
말 그대로 운동, 튀는 등과 같은 공에 대한 모든 논리를 포함하는 Ball이라는 구성 요소와 입력을받는 Paddle 구성 요소가 있지만 그게 나입니다. 그리고 이것이 "컴포넌트 시스템이란 무엇인가"에 대해 각 프로그래머마다 하나의 의견이있는 이유입니다. 고전적인 엔티티 시스템을 완전히 생각하고 구성 요소 시스템을 사용해야하지만 실제로 차이점이 무엇인지보고 싶지 않다는 점을 제외 하고는이 제안과 같이 하지 않는 것이 좋습니다 .
Imi

2
@lmi : 구성 요소가있는 몇 가지 큰 게임 / 엔진에서 일하면서 구성 요소 를 사용하는 이유를 직접 살펴 보았습니다 . 아니요, 지나치게 세분화 된 구성 요소는 가치보다 더 많은 문제입니다. 컴포넌트는 마법의 총알이 아닙니다. 그것들은 게임 개발자 도구 상자에있는 많은 도구 중 하나입니다. 시스템에 더 많은 정신적 및 런타임 오버 헤드를 추가하는 방식이 아니라 도움이되는 방식으로 사용하십시오. 공 물리학을 가지고있는 유일한 것은 공 인 경우가 제로 다른 볼 속성에서 분리에 이용. 변경 사항이 있으면 변경 한 다음 분할하십시오.
Sean Middleditch 2016 년

1
나는 실용적이고 특정 후두둑이 길을 들이지 못하게하는 원칙에 동의합니다. 그러나 ECS가이 사소한 게임을 편차없이 처리 할 수 ​​없다면 큰 게임에 대한 희망은 무엇입니까? 나도 ECS를 효과적으로 사용하는 방법을 배우려고 노력하고 있지만 가능한 한 ECS 철학에 가깝게 유지하려고 노력하고 있습니다. 그렇지 않으면 예외와 특수 사례를 만들기 시작하면 유지할 수없는 혼란에 빠질 것입니다.
Ken

-2

내 의견 *)에서, 구성 요소와 함께 가장 큰 문제는 이것이다 : 구성 요소가 여기되지 않은 이야기 할 수있는 어떤 다른 사람을. 구성 요소는 여기에 있습니다. 당신은 단지 어떤 것의 기억을 유지하기 위해 구성 요소가 없으며 다른 구성 요소가 이것에 작동하도록합니다. 얻은 데이터로 작업하는 구성 요소가 필요합니다.

다른 구성 요소가 있는지 테스트 한 다음 함수를 호출하면 다음 두 가지 중 하나에 해당한다는 분명한 신호입니다.

  • 실제로 종속성을 반전 시키려고합니다. 다른 구성 요소는 현재 구성 요소에 대한 응답으로 논리를 실행하기 위해 이벤트 / 메시지 / 브로드 캐스트 / 후크 / 이름을 듣습니다. 현재 구성 요소는 "다른"구성 요소가 있다는 것을 알 필요조차 없습니다. 현재 메서드에 실제로 연결되지 않은 기능으로 다른 구성 요소 (다른 블록 / 케이스 블록에서도)를 호출하는 경우가 가장 흔합니다. 이 모든 것을 생각 Invalidate()하거나 SetDirty()다른 구성 요소를 호출하십시오.
  • 구성 요소가 너무 많을 수 있습니다. 두 구성 요소가 서로없이 살 수없고 지속적으로 데이터를 검색하고 서로에게 메서드를 호출해야하는 경우 이들을 병합하면됩니다. 분명히, 그들이 제공하는 기능은 너무 얽혀서 실제로 실제로는 한 가지입니다.

그건 그렇고, 이것들은 엔티티 / 컴포넌트 시스템뿐만 아니라 단순한 "GameObject"또는 라이브러리 함수를 이용한 클래식 상속에도 모든 종류의 시스템에 적용됩니다.

*) 정말 내 것 입니다. Whats Da Real Component Systemz (TM)에 대한 의견이 크게 다름

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