컴포넌트 기반 설계의 입력 처리


12

이 질문이 여러 번 요청 된 것을 알고 있지만 여전히 컴포넌트 기반 엔진에서 입력 처리를 구현하는 방법을 잘 모르겠습니다.

내가 사용한 컴포넌트 기반 디자인은 T = Machine 의 블로그 시리즈와 엔티티가 ID 인 Artemis 를 기반으로했다 .

입력 처리를 구현할 때 세 가지 주요 아이디어가 있습니다.

  1. 입력 구성 요소는 관심있는 이벤트를 보유합니다. 입력 시스템은 키 및 마우스 이벤트를 게임 이벤트로 변환하고 입력 구성 요소를 사용하여 엔티티를 반복하며 이벤트에 관심이있는 경우 입력 시스템에서 적절한 조치를 취합니다. 이 조치는 입력 시스템에 하드 코딩됩니다.
  2. 입력 컴포넌트가 없습니다. 특정 이벤트가있는 엔터티를 입력 시스템에 등록합니다. 그런 다음 입력 시스템은 적절한 조치를 취할 수 있도록 다른 시스템에 메시지 (엔터티 ID 및 이벤트 유형)를 보냅니다. 또는 첫 번째 경우와 마찬가지로 작업은 입력 시스템에 하드 코딩됩니다.
  3. 첫 번째 방법과 유사하지만 입력 시스템에 작업을 하드 코딩하는 대신 구성 요소 std::map<std::function>에 입력 시스템에 의해 호출되는 함수에 대한 이벤트 맵 (예 :)이 포함 됩니다. 이는 동일한 이벤트를 다른 조치에 결합 할 수있는 추가 효과가 있습니다.

위의 방법 중 하나를 추천 하시겠습니까? 아니면 유연한 입력 처리 시스템을 구현하는 데 도움이되는 제안이 있습니까? 또한 아직 멀티 스레딩에 익숙하지 않지만 구현을 스레드 친화적으로 만드는 제안도 환영합니다.

참고 : 구현이 이행하기를 원하는 한 가지 추가 요구 사항은 카메라 엔터티와 플레이어를 동시에 이동하는 것과 같이 많은 항목에 동일한 입력을 전달할 수 있어야한다는 것입니다.


2
일반적으로 (카메라가 플레이어를 따라갈 때) 카메라에서 입력을받지 않으려는 대신 카메라가 플레이어 위치를 확인하고 따라갑니다.
Luke B.

1
카메라가 플레이어를 따르는 지 또는 "자체"인지는 개념적으로 중요하지 않습니다. 그럼에도 불구하고 디자인 원칙을 어 기지 않고 구성 요소 기반 디자인에서 제안이 어떻게 구현되는지 확실하지 않습니다.
Grieverheart

1
@Luke B .: 몇 가지 생각을 한 후에, 카메라를 별도의 클래스로 만들 수 있으며 따라야 할 엔티티에 대한 포인터를 가져갈 수 있습니다.
Grieverheart

답변:


8

컴포넌트 시스템의 머티리얼대한 제 답변과 마찬가지로 모든 것을 "컴포넌트"로 밀어 넣으려고하는 문제가 발생한다고 생각합니다. 이 작업을 수행 할 필요가 없으며 그렇게하면 사각형 구멍 묶음을 둥근 구멍에 끼워서 정말 귀찮은 인터페이스를 만들 수 있습니다.

이미 플레이어의 입력 획득을 처리하는 시스템이있는 것 같습니다. 그런 다음 해당 입력을 동작 ( "앞으로 이동"또는 "뒤로 이동") 또는 이벤트로 변환하고 이해 당사자에게 전달하는 접근 방식을 선택합니다. 과거 에는 상위 수준의 시스템이 "제어 대상"을 명시 적으로 선택한 방식을 선호하여 구성 요소가 이러한 이벤트에 자신 을 등록하지 못하게 했습니다 . 그러나 원하는 경우 다른 방식으로 작동 할 수 있습니다. 특히 입력으로 직접 자극되지 않은 조치를 수행하기 위해 동일한 메시지를 재사용하려는 경우에 특히 그렇습니다.

그래도 카메라 엔터티와 플레이어 엔터티 모두 "앞으로 이동"메시지에 응답하여 카메라 팔로우 동작을 구현할 것을 권장하지는 않습니다. 이것은 플레이어에게 좋지 않을 것 같은 두 객체 사이에 매우 견고한 연결을 만들고 플레이어가 왼쪽 또는 오른쪽으로 회전 할 때 카메라 궤도 플레이어와 같은 것을 처리하는 것이 조금 까다로워집니다. 플레이어에게 종속되어 있다고 가정하여 "왼쪽으로 회전"에 응답하지만, 슬레이브가 아니었다면 올바르게 응답 할 수 없다는 것을 의미합니다. 그리고 그렇게하려는 경우, 두 개의 물리적 객체를 함께 슬라브하기위한 적절한 시스템을 구현하고 적절한 탄성 조정 등을 완료 할 수 있습니다.

멀티 스레딩과 관련하여 가치가있는 것보다 더 복잡한 문제가 발생할 수 있으므로 여기에서 채택해야 할 필요는 없으며 본질적으로 직렬 문제를 처리하므로 많은 스레드가 필요합니다. 동기화 프리미티브.


나는 내 질문에 약간의 생각을했고 스스로 대답하려고했다. 또한 EC 시스템에서 입력 처리를 분리하는 것이 더 좋으므로 결론을 확인하는 것이 좋습니다. 내가 생각한 방법은 신호를 사용하고 여러 엔티티를 이벤트 유형에 연관시키는 기능입니다. 나는 또한 카메라를 분리하기로 결정했지만 실제로는 필요하지 않으며 엔티티로 사용하는 것도 똑같이 가능합니다. EC와 함께 초보자 일 때 어떤 것이 구성 요소 나 엔터티를 만들면 어떤 이점이 있는지 생각해야한다고 생각합니다.
Grieverheart

4

내 경험은 편견이있을 수 있지만 다중 플랫폼 프로젝트에서는 입력 장치가 엔터티 시스템에 직접 노출되지 않습니다.

입력 장치는 키, 버튼, 축, 마우스, 터치 표면, 가속도계 등에서 이벤트를 수신하는 하위 시스템으로 처리됩니다.

그런 다음 이러한 이벤트는 컨텍스트 종속 의도 생성기 계층을 통해 전송됩니다.

각 발생기 레지스터는 해당 기능과 관련된 구성 요소, 엔티티 및 시스템의 상태 변경을 등록합니다.

그런 다음이 생성기는 엔터티가 구성 요소가있는 의도 시스템으로 또는 올바른 구성 요소로 직접 라우팅 할 메시지 / 의도를 보냅니다.

이런 식으로 JUMP_INTENT (1), JUMP_INTENT (0), AIM_INTENT (1) 같은 입력을 가진 "항상"에 의존 할 수 있습니다.

더티 플랫폼 종속 입력 작업은 "모두"엔터티 시스템 외부에 남아 있습니다.


카메라를 플레이어 주위로 옮기려면 카메라가 자체 의도 구성 요소를 등록하고 보낼 의도를들을 수 있습니다.

그렇지 않으면 플레이어를 따라갈 때 플레이어로 향하는 입력을 듣지 않아야합니다. 플레이어 (ENTITY_MOVED (transform))가 방출 한 상태 변경 사항을 듣고 그에 따라 이동해야합니다. 물리 시스템을 사용하는 경우 다양한 관절 중 하나를 사용하여 카메라를 플레이어에 연결할 수도 있습니다.


코요테, 답변 주셔서 감사합니다. 나는 또한 다른 게시물을 읽고 여기에 . 가장 큰 관심사는 입력을 추상화하는 방법이 아닙니다. 나는 이미 키 누름 등을 처리하는 하위 레벨 구조를 가지고 있으며 하나 이상의 간접 레벨을 추가하는 것은 어렵지 않습니다. 내 문제는 예를 들어 의도 시스템에서 생성 된 이벤트를 처리하는 것입니다. 올바르게 이해하면 방법에 입력 구성 요소가 전혀 없습니다. 어떤 엔터티가 입력이 필요한지 어떻게 알며 어떻게 처리합니까? 좀 더 구체적인 예를 들어 주시겠습니까?
Grieverheart

2

InputComponent는 어떤 이점을 제공합니까? 확실히 어떤 명령을 수행 할 엔티티를 결정하는 것이 input 명령의 특권입니다. 전형적인 예는 플레이어를 점프시키는 것입니다. "Jump"이벤트를 수신하는 모든 엔터티에 InputComponent를 사용하는 대신 "player"로 표시된 엔터티를 점프 명령으로 조회하여 필요한 로직 자체를 수행하지 않는 이유는 무엇입니까?

Action jump = () =>
{
    entities["player"].Transform.Velocity.Y += 5;
};

OP의 또 다른 예 :

Action moveRight = () =>
{
    foreach (var entity in entities.Tagged("player", "camera"))
        entity.Transform.Position.X += 5;
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.