컴포넌트 기반 엔터티 시스템의 게임 상태 및 입력 처리


16

내 질문은 :

게임 상태 객체 스택을 유지하지 않고 엔티티 시스템에서 게임 상태를 어떻게 처리 할 수 ​​있습니까?

따라서 엔터티 시스템의 디자인은 엔터티가 입력 이벤트에 등록해야 할 때 입력 구성 요소가 입력 시스템을 호출하고 "이 엔터티에이 엔터티를 등록합니다"라는 의미입니다. 이것은 모두 훌륭하지만, 게임 상태 개념 (일시 정지 화면)을 추가하면 엔티티가 현재 상태에 있고 입력을 받아야하는 경우 문제가됩니다.

"이 게임 상태에있는 동안이 입력에이 엔티티를 등록하십시오"라고 입력 컴포넌트 / 시스템을 확장 할 수 있지만, 모든 엔티티가 어떤 상태에서 사용 될지 알고 있어야하며 이는 명확하지 않을 수 있습니다. 또한 등록 된 입력 (및 콜백을 사용하는 다른 시스템)별로 게임 상태 목록을 유지하는 것이 너무 효율적이지 않습니다.

내가 가진 또 다른 아이디어는 게임 상태를 나타내는 엔터티가 있기 때문에 비활성화 된 것으로 표시 한 다음 입력 이벤트를 생성 할 때 엔터티가 비활성화 된 게임 상태 엔터티의 자손이 아닌지 확인합니다. 모든 콜백에 대해 부모를 해결하는 데 비용이 많이 드는 것 같습니다.

또 다른 아이디어는 모든 시스템이 현재 상태를 기준으로 데이터를 저장하도록하는 것입니다. 입력을 생성 할 때 대상 엔터티도 후보가되지 않습니다. 그러나 이것은 다른 상태의 엔티티 간 통신을 허용하는 기능을 실제로 손상시킵니다 (일시 중지 화면의 문제는 아니지만 Oblivion / Skyrim에서 잠금 선택을 생각하십시오).

내가 가진 유일한 다른 아이디어는 모든 구성 요소가 상태 변경 이벤트를 처리하고 관련 시스템과 통신하여 등록 된 모든 것을 비활성화 하고이 상태로 다시 전환 할 때 다시 활성화하는 것입니다.

두 번째 (객체를 비활성화 된 것으로 표시)와 앞뒤 (각 구성 요소가 상태 변경을 처리하게 함)는 내 아이디어 중 가장 좋은 것처럼 보이지만 그중 어느 것도 나에게 특히 뛰어나지는 않습니다.

다른 사람이 이것을하는 방법에 대한 다른 아이디어가 있습니까?

편집 이 질문에서 구체적으로 입력에 대해 이야기하는 동안 충돌, 타이머 이벤트 등과 같은 엔티티에 메시지 / 이벤트를 보낼 수있는 모든 시스템을 의미 할 수 있습니다 ...


6
나는 이것을 좋아한다 : 나는 스크린, MenuScreen PauseScreen GameScreen을 가지고 있으며, 각 스크린은 자신의 월드 (엔티티를위한 컨테이너)와 시스템 (렌더링 시스템과 같은)을 생성 할 수 있고 게임 스크린에서 월드, 카메라 컴포넌트를 가진 엔티티를 만들고 CameraComponent.RenderTarget을 화면 배경. 이 방법으로 단순화 된 렌더러와 같은 자체 엔티티 및 시스템을 갖는 InventoryScreen을 추가 할 수 있습니다. 입력은 화면에서 세계로 전달 될 수 있으므로 사용자 인터페이스는 입력이 화면으로 전달되는지 (초점이
있거나


2
@ Byte56 사실, 첫 번째 것은 게임 상태와 관련이 있으며 (다른 두 개는 엔터티 내의 상태), 실제로 내가 가진 것과 동일한 문제를 해결하지는 못합니다. 게임이 일시 정지 상태에있을 때, 플레이어 시스템에 움직임 메시지를 보내는 것을 막기 위해 입력 시스템에 무언가가 발생해야합니다 (예를 들어), 나는 이것을하는 좋은 방법을 알아낼 수 없습니다.
elFarto

1
좋아요, 그때 관련성을 고려하십시오. 좋은 질문.
MichaelHouse

1
과거에 내 구성 요소 기반 시스템에 짜증이 났을 다른 것들을 고려해야합니다 : 멀티 레이어 UI. 세계 또는 다단계 화면 상단에 대화 상자가 나타납니다. 내가 만든 모든 게임에서 지금까지 나왔으므로 그 문제를 해결할 수있는 접근법을 고려해야한다고 말하고 싶습니다.
ADB

답변:


14

자주 사용되는 것은 Intent System입력을 추상화하고 컨텍스트와 관련 게임 상태를 추적 하는 중간체 입니다.

예를 들어 인 텐트 시스템은 시뮬레이션이 일시 정지 될 때 입력 전송을 중단합니다. 또한 컨트롤러 이벤트와 의도 (방향으로 이동, 실행, 촬영, 다시로드 ...) 간의 매핑을 처리합니다.

이 방법으로 다른 참가자는 특정 게임 패드 / 입력 (BUTTON_A, BUTTON_B vs BUTTON_X, BUTTON_O ...)에 의존하지 않지만 모두 동일한 의도 (IntentRun, IntentReload ...)에 반응합니다.

또 다른 장점은 인 텐트 시스템은 인 텐트를 처리 할 수있는 시뮬레이션 외부에서도 모든 가입자에게 인 텐트를 보낼 수 있으므로 사용 가능한 컨트롤러가 추가 / 제거되는 것을 인식 할 수 있다는 것 AddPlayer(controllerID)입니다.

이벤트 / 메시지를 통해 또는 시스템에 제공 한 게임 상태에 대한 정보의 양은 귀하에게 달려 있습니다. 그러나 인 텐트 시스템에 투자 한 시간은 일반적으로 그만한 가치가 있습니다.

의도 컨텍스트가 시스템에 연결될 때 의도를 생성하는 의도 컨텍스트를 관리 할 수 ​​있습니다.

문맥은 우선 순위를 정할 수 있습니다 :

  • SimulationAvailableContext는 카메라 이동, 확대 / 축소, 플레이어 추가 / 제거와 같이 사용 가능하지만 실행 중이 아닌 동안 시뮬레이션에 인 텐트를 보냅니다.
  • SimulationRunningContext는 일시 정지되지 않은 상태에서 시뮬레이션에 인 텐트를 전송합니다. 플레이어 이동, 유닛을 위치로 전송, 촬영 ...

이런 식으로 현재 관련된 컨텍스트를 추가하고 제거 할 수 있습니다.

전체 의도 시스템에 대한 한 가지는 시뮬레이션이 일시 중지 된 상태에서 실행되어야한다는 것입니다.

비 시뮬레이션 관련 업데이트를 중단하지 않고 게임 시뮬레이션을 재생 / 일시 정지하는 데 자주 사용되는 한 가지 방법은 다른 시간 세트를 사용하는 것입니다. 즉 GenericSystem::onTime(Long time, Long deltaTime, Long simTime, Long simDeltaTime).

이 접근 방식을 통해 엔진은 게임의 simTime에서 증가분을 간단히 차단할 수 있으며, 이는 simTime and simDeltaTime일시 정지 중에도 이동 해야하는 경우 카메라 스프링 효과를 지속적으로 업데이트하면서 사용 하는 관련 애니메이션 및 물리 엔진의 업데이트를 차단합니다. 데이터가 다운로드되는 동안 게임 내 가상 광고판에 대한 로딩 효과 ...


나는 이것이 모든 엔터티에 대해 "State Changed"함수를 호출 할 필요가 없다는 사실을 좋아합니다. 잘못된 시간에 잘못된 의도가 전송되는 것에 대해 걱정해야하지만 대안보다 낫습니다.
토마스 마넬

엔티티는 점프와 같은 의도를 무시할 수 있지만 상태는 점프 할 수 없습니다 (즉,지면을 건드리지 않음). 그러나 게임이 일시 중지 된 동안 이러한 의도를받는 것에 대해 걱정할 필요가 없습니다.
코요테

나는 엔터티가 입력 시스템에 메시지를 전달할 상태를 알려주는 것을 이미 생각했지만 입력 자체에 상태를 넣는 것을 생각하지 않았으므로 좋은 생각입니다. 또한 시간과 simTime을 분리하는 것도 좋습니다.
elFarto

시뮬레이션 관련이 아닌 것으로 시뮬레이션 관련 상태를 부 풀리지 않아야합니다. 모든 UI 및 플레이어 관련 코드를 시뮬레이션 자체에서 최대한 멀리 이동시키고 시뮬레이션에서 의도에만 집중하십시오.
코요테

@Coyote,이 시스템은 매우 흥미롭게 들린다. 이 질문 에 대답 하여 더 많은 정보를 제공해 주 시겠습니까? 감사!
pek

2

글로벌 이벤트 시스템을 작성한 다음 각 엔티티에 대한 이벤트 리스너 구성 요소를 사용하는 것은 어떻습니까? "게임 상태 변경"이벤트 후에는 각 특정 엔티티에 대해 개별적으로 컴포넌트를 피들 링 할 수 있습니다.

입력 컴포넌트가 있다고 가정 해 봅시다. 이벤트 리스너 구성 요소는 게임 상태 변경 이벤트를 수신 한 후 해당 특정 입력 구성 요소에 대해 매우 특정한 값을 변경하므로 입력 호출을받지 않거나 시스템 또는 소유자에게 이동 또는 응답 호출을하지 않습니다.

대부분의 구성 요소가 (루아를 통해) 스크립팅되므로 이는 나에게 효과적입니다. 즉, 입력 구성 요소가 있습니다. 키를 누르면 한 번 트리거되고 이동 + 방향으로 발사 한 다음 키를 놓으면 정지 + 방향으로 발사됩니다. 입력 컴포넌트 (게임이 일시 정지 된 경우)와 접촉하여 함수 발생을 멈추고 필요한 경우 정지하는 이벤트 리스너 컴포넌트도 있습니다. 그런 다음 다른 스크립트를 사용하여 동일한 이벤트 및 키 누르기에 다른 반응을 가진 다른 엔티티를 쉽게 추가 할 수 있습니다. 이 방법을 사용하면 다른 주에서 서로 다른 엔티티 간의 상호 작용을 저장하고 훨씬 더 사용자 정의 할 수 있습니다. 또한 일부 엔티티에는 이벤트 리스너 구성 요소가 없을 수도 있습니다.

방금 설명한 것은 기본적으로 네 번째 솔루션의 실용적인 예입니다.

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