구성 요소 엔티티 시스템-업데이트 및 호출 주문


10

구성 요소가 모든 프레임 을 업데이트 할 수있게하고 (필요하지 않은 구성 요소에서이 기능을 사용하지 않도록) UpdateComponent 구성 요소를 만드는 아이디어를 얻었습니다. MovableComponent속도를 유지하는 것과 같은 다른 구성 요소 는 IUpdatable추상 클래스 에서 상속됩니다 . 이렇게 하면에 대한 포인터를 제공 MovableComponent하는 Update(gametime dt)메소드와 다른 메소드를 강제 로 구현 합니다 . 많은 구성 요소가이 작업을 수행 한 다음 누가 또는 무엇인지 신경 쓰지 않고도 모든 메서드를 호출 할 수 있습니다.RegisterWithUpdater()UpdateComponentMovableComponentUpdateComponentUpdate(gametime dt)

내 질문은 :

  1. 이것이 정상이거나 누군가가 사용하는 것 같습니까? 주제에서 아무것도 찾을 수 없습니다.
  2. 물리와 같은 구성 요소에 대한 순서를 유지 한 다음 위치를 변경하려면 어떻게해야합니까? 이것도 필요합니까?
  3. 모든 프레임에서 처리해야하는 구성 요소가 실제로 처리되도록하는 다른 방법은 무엇입니까?

편집
엔터티 관리자에게 업데이트 가능한 유형 목록을 제공하는 방법에 대해 생각할 것입니다. 그런 다음 해당 유형의 모든 구성 요소는 엔터티 당 관리하지 않고 업데이트 할 수 있습니다 (어쨌든 내 시스템의 색인 일뿐입니다).

아직도. 내 질문은 계속 유효합니다. 이것이 합리적인 이유인지 다른 사람들이하는 경향이 있는지 모르겠습니다.

또한 Insomniac 의 사람들 은 굉장합니다! /편집하다

이전 예제의 코드를 정리했습니다 :

class IUpdatable
{
public:
    virtual void Update(float dt) = 0;
protected:
    virtual void RegisterAsUpdatable() = 0;
};

class Component
{
    ...
};

class MovableComponent: public Component, public IUpdatable
{
public:
    ...
    virtual void Update(float dt);
private:
    ...
    virtual void RegisterWithUpdater();
};

class UpdateComponent: public Component
{
public:
    ...
    void UpdateAll();
    void RegisterUpdatable(Component* component);
    void RemoveUpdatable(Component* component);
private:
    ...
    std::set<Component*> updatables_;
};

업데이트 할 수없는 구성 요소에 대한 예가 있습니까? 꽤 쓸모없는 것 같습니다. 업데이트 기능을 가상 기능으로 컴포넌트에 넣습니다. 그럼 그냥 엔티티의 모든 구성 요소를 업데이트은 "UpdateComponent"에 대한 필요가 없습니다
Maik Semder

일부 구성 요소는 데이터 홀더와 비슷합니다. PositionComponent처럼. 많은 개체가 위치를 가질 수 있지만 대부분 고정 될 수있는 고정 된 개체 인 경우 추가 가상 호출이 모두 발생할 수 있습니다. 또는 HealthComponent라고 말하십시오. 모든 프레임을 수행 할 필요가 없으며 필요할 때 수정하면됩니다. 어쩌면 오버 헤드가 그렇게 나쁘지는 않지만 내 UpdateComponent는 모든 구성 요소에 Update ()가없는 시도였습니다.
ptpaterson

5
데이터 만 보유하고 시간이 지남에 따라 데이터를 변경하는 기능이없는 구성 요소는 정의상 구성 요소가 아닙니다. 구성 요소에는 시간이 지남에 따라 변경되는 일부 기능이 있어야하므로 업데이트 기능이 필요합니다. 구성 요소에 업데이트 기능이 필요하지 않은 경우 구성 요소가 아니라는 것을 알고 디자인을 다시 생각해야합니다. 건강 구성 요소의 업데이트 기능은 의미가 있습니다. 예를 들어 NPC가 일정 시간 동안의 손상으로부터 치유되기를 원합니다.
Maik Semder

@Maik 필자의 요점은 결코 / 변경 될 수없는 구성 요소가 아니다. 나는 바보 같은데 동의합니다. 그들은 모든 프레임을 업데이트 할 필요가 없으며 필요할 때 정보를 변경하라는 알림을받습니다. 건강 상태가 시간이 지남에 따라 업데이트 된 건강 보너스 구성 요소가있을 수 있습니다. 나는 두 가지를 결합 할 이유가 없다고 생각합니다.
ptpaterson

또한 게시 한 코드에는 UpdateComponent 개념을 설명하는 데 필요한 내용 만 포함되어 있습니다. 구성 요소 간의 다른 모든 통신 형식은 제외합니다.
ptpaterson

답변:


16

구성 요소 시스템의 주요 이점 중 하나는 동일한 코드를 반복해서 실행하기 때문에 우수한 icache 및 예측, 균일 한 풀에 객체를 할당 할 수 있고 vtable, 어쨌든 뜨겁습니다.

구성 요소를 구성한 방식에 따라이 이점은 완전히 사라지고 실제로 vtables를 사용하여 훨씬 더 많은 가상 호출과 더 많은 객체를 만들 때 상속 기반 시스템에 비해 성능 책임이 될 수 있습니다.

해야 할 일은 유형별로 풀을 저장하고 각 유형을 독립적으로 반복하여 업데이트를 수행하는 것입니다.

이것이 정상이거나 누군가가 사용하는 것 같습니까? 주제에서 아무것도 찾을 수 없습니다.

큰 게임에서는 유리하지 않기 때문에 일반적이지 않습니다. 많은 게임에서 일반적이지만 기술적으로 흥미롭지는 않으므로 아무도 그것에 대해 쓰지 않습니다.

물리와 같은 구성 요소에 대한 순서를 유지 한 다음 위치를 변경하려면 어떻게해야합니까? 이것도 필요합니까?

C ++와 같은 언어로 된 코드는 자연스럽게 실행을 주문하는 방법이 있습니다. 문장을 순서대로 입력하십시오.

for (PhysicsComponent *c : physics_components)
    c->update(dt);
for (PositionComponent *c : position_components)
    c->update(dt);

실제로는 물리 시스템이 그렇게 강력하게 구성되어 있지 않기 때문에 이치에 맞지 않습니다. 하나의 물리 객체를 업데이트 할 수 없습니다. 대신 코드는 다음과 같습니다.

physics_step();
for (PositionComponent *c : position_components)
    c->update(dt);
// Updates the position data from the physics data.

감사. 캐시 지향 등을 방지하기 위해 데이터 중심 (데이터 기반과 같지 않음)을 염두에 두고이 전체 프로젝트를 시작했습니다. 그러나 일단 코딩을 시작하면 닷컴에서 작동하는 것을 만들기로 결정했습니다. 그것이 나를 힘들게 만드는 것으로 밝혀졌습니다. 그리고 심각하게도, 그 불면증 기사는 훌륭했습니다!
ptpaterson

@Joe +1은 아주 좋은 답변입니다. icache와 dcache가 무엇인지 알고 싶습니다. 감사합니다
Ray Dey

명령 캐시 및 데이터 캐시 컴퓨터 아키텍처에 대한 모든 소개 텍스트를 포함해야합니다.

@ptpaterson : Insomniac 프리젠 테이션에는 약간의 실수가 있습니다. 컴포넌트 클래스에는 로스터 인덱스가 포함되어 있거나 풀 인덱스와 로스터 인덱스를 별도로 매핑해야합니다.

3

당신이 말하는 것은 합리적이고 상당히 일반적입니다. 이것은 당신에게 더 많은 정보를 줄 수 있습니다.


나는 몇 주 전에 그 기사를 발견했다고 생각합니다. 구성 요소 기반 엔터티 시스템의 몇 가지 매우 간단한 버전을 서로 코딩 할 수있었습니다. 각기 다른 일을 시도 할 때마다 다릅니다. 모든 기사와 예제를 모두 내가 원하고 할 수있는 것으로 모 으려고합니다. 감사!
ptpaterson

0

나는 이러한 접근법을 좋아한다.

곧 : 구성 요소 내에서 업데이트 동작을 유지하지 마십시오. 구성 요소 동작 하지 않습니다 . 일부 단일 인스턴스 서브 시스템에서 동작 (업데이트 포함)을 구현할 수 있습니다. 이 접근 방식은 여러 구성 요소에 대해 유사한 동작을 일괄 처리하는 데 도움이 될 수 있습니다 (구성 요소 데이터에 대해 parallel_for 또는 SIMD 명령 사용).

IUpdatable idea and Update (gametime dt) 방법은 너무 제한적이며 추가 의존성을 도입합니다. 서브 시스템 접근 방식을 사용하지 않는 것이 좋을 수도 있지만,이를 사용하는 경우 IUpdatable은 중복 레벨의 계층 구조입니다. 결국, MovingSystem은 이러한 구성 요소가있는 모든 엔티티에 대해 위치 및 / 또는 속도 구성 요소를 직접 업데이트해야하므로 중간 IUpdatable 구성 요소가 필요하지 않습니다.

그러나 업데이트 가능 구성 요소를 위치 및 / 또는 속도 구성 요소가 있지만 일부 개체 업데이트를 건너 뛰는 메커니즘으로 사용할 수 있습니다. 업데이트 가능 구성 요소는 설정 될 수있는 부울 플래그를 가질 수 있으며, false이 특정 엔티티가 현재 업데이트되어서는 안된다는 모든 업데이트 가능 인식 하위 시스템에 신호를 보냅니다.

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