엔터티 시스템의 많은 이동원 구성 요소가있는 엔터티가 있습니다. 그런 다음 게임에서

나는 잔뜩 읽은, 기업 시스템의 개념에 비교적 새로운 해요 (대부분의 유용, 이 위대한 블로그이 답변 ).

정의되지 않은 수의 소스로 객체의 위치를 ​​조작하는 것만 큼 간단한 것이 무엇인지 이해하는 데 약간의 어려움이 있습니다.

즉, 직위 구성 요소가있는 엔터티가 있습니다. 그런 다음 게임에서 일정 시간 동안이 엔티티가 주어진 거리를 이동하도록 지시하는 이벤트가 있습니다.

이러한 이벤트는 언제든지 발생할 수 있으며 위치와 시간에 대해 다른 값을 갖습니다. 결과적으로 서로 합성됩니다.

전통적인 OO 솔루션에서는 MoveBy거리 / 시간을 포함하는 일종의 클래스와 게임 객체 클래스 내부에 배열이 있습니다. 각 프레임마다 모든을 반복 MoveBy하고 위치에 적용합니다. A는 경우 MoveBy의 마무리 시간에 도달, 배열에서 제거합니다.

엔터티 시스템에서는 이러한 종류의 동작을 어떻게 복제해야하는지 약간 혼란스러워합니다.

한 번에 이들 중 하나만 있으면 함께 합성 할 수있는 것이 아니라 매우 간단하고 (믿습니다) 다음과 같이 보입니다.

PositionComponent 포함 x, y

MoveByComponent 포함 x, y, time

Entity어느 a PositionComponent와 aMoveByComponent

MoveBySystem이 두 구성 요소가 모두있는 엔티티를 찾고의 값을 MoveByComponent에 추가 합니다 PositionComponent. time에 도달 하면 해당 엔티티에서 구성 요소를 제거합니다.

나는 많은 움직임으로 어떻게 똑같은 일을하는지에 대해 약간 혼란 스럽습니다.

나의 초기 생각은 내가 가질 것이라는 것입니다.

PositionComponent, MoveByComponent상기와 동일

MoveByCollectionComponent배열 함유하는 MoveByComponent

MoveByCollectionSystema PositionComponent와 a가 있는 엔티티를 찾고 내부 MoveByCollectionComponentMoveByComponents를 반복하여 필요에 따라 적용 / 제거합니다.

나는 이것이 동일한 구성 요소를 많이 가지고 있고 해당 시스템이 각 구성 요소에 작용하기를 원한다는보다 일반적인 문제라고 생각합니다. 내 엔터티에는 구성 요소 유형-> 구성 요소의 해시 안에 해당 구성 요소가 포함되어 있으므로 엔터티 당 특정 유형의 구성 요소가 하나만 엄격하게 있습니다.

  1. 이것이 이것을 보는 올바른 방법입니까?

  2. 엔터티는 항상 주어진 유형의 구성 요소를 항상 하나만 가져야합니까?



답변

시나리오의 경우 일반적으로 게임 개체에 세 가지 구성 요소를 추가합니다.

  1. TransformComponent (위치, 방향, 스케일)
  2. 속도 성분 (속도, 방향)
  3. 컨트롤러 컴포넌트

게임 오브젝트가 설명대로 경로를 따라 이동하는 것과 같은 AI 기능이 필요한 경우 AIController를 구성 요소 목록에 할당합니다. AI 컨트롤러는 실제로 행동 트리를 수행하는 래퍼 외에는 아무것도 아닙니다. 비헤이비어 트리는 다음과 같이 게임 오브젝트가 수행하도록하는 실제 기능을 디자인하는 곳입니다.

BehaviorTree* tree(new SequentialNode());
tree->addChild(new MoveToNode(x,y,z));
tree->addChild(new WaitNode(30));
tree->addChild(new MoveToNode(a,b,c));
tree->addChild(new WaitNode(30));
gameObject->addComponent(new AIController(tree));

AI 하위 시스템은 AIController를 관리하므로 하위 시스템이 컨트롤러를 선택하여 동작 트리를 단계적으로 수행합니다. MoveToNode ()는 현재 위치 / 방향을보고 생성자 인수를 기반으로 이동하려는 방향 벡터 및 속도를 계산하고 속도 구성 요소의 값을 설정합니다. 이동 시스템은 값을 갖는 이동 구성 요소를 읽고 물리를 적용하여 그에 따라 위치 / 방향을 업데이트하는 역할을한다.

위의 코드는 월드 공간에서 게임 오브젝트를 스폰 위치에서 x, y, z로 이동 한 다음 최소 30 초 동안 기다린 다음 게임 오브젝트를 위치 a, b, c로 이동 한 다음 30 초 더 기다립니다. 대기가 끝나면 동작 순서가 완료되었으므로 처음부터 반복됩니다.

이를 통해 엔티티 서브 시스템에 미치는 영향을 최소화하면서 AI 서브 시스템에 필요한 모든 AI 기능을 쉽게 정의 할 수 있습니다. 또한 엔터티 시스템 구성 요소 목록을 너무 세분화하지 않고 간결하게 유지할 수 있습니다.


답변

옵션은 디자인에 컨트롤러를 추가하는 것입니다. 엔터티는 위치를 나타내는 데이터를 소유합니다 (내 엔진의 경우 이전 위치도 기억하는 데이터가 있으므로 속도 벡터를 알 수 있으며 이동 또는 순간 이동중인 경우). 물리학 또는 일체 포함. 컨트롤러는 엔터티를 이동하며 동일한 엔터티에 영향을주는 많은 컨트롤러 나 다양한 엔터티에 영향을주는 하나의 컨트롤러를 가질 수 있습니다.

예를 들어 : run () 메소드를 사용하여 기본 Controller 클래스를 작성하거나 이름 호출이 마음에 들지 않으면 think (), update () 또는 tick ()을 호출하십시오. 그런 다음 그로부터 상속하여 MoveController, NPCController, PlayerInputController (플레이어 엔티티 용), PhysicController를 만듭니다. 그런 다음 run () 메소드를 구현하십시오. Entity가 아닌 MoveController에 MoveByComponent를 넣을 것입니다.

이러한 컨트롤러는 엔터티에 특정한 데이터를 보유하는 경우 각 엔터티에 의해 인스턴스화 될 수 있습니다. 그것들은 재사용을 위해 파괴되거나 재설정 될 수 있습니다. 예를 들어 RTE 게임에서 컨트롤러를 사용하여 엔티티 그룹을 이동할 수 있습니다. 예를 들어, 다양한 유닛을 그룹으로 이동해야 할 경우 각 유닛별로 컨트롤러를 사용하면 게임 성능이 저하 될 수 있습니다. GroupController 또는 LegionController로 이동하여 구성된 그룹의 일부로 단위를 이동시킵니다. 싸우는 경우 게임에서 개별 단위 동작을 허용하고 대부분의 게임에서 허용하는 경우 UnitController로 전환해야하지만 필요할 때만 처음부터하는 것이 좋습니다.

개발중인 게임에는 경로를 따라 엔티티를 이동시키는 MoveController가 있으며 각 NPC와 플레이어 캐릭터마다 하나의 MoveController가 있습니다. 때때로 플레이어가 밀 수있는 상자 나 바위를 위해 하나가 만들어집니다. 일부 엔티티가 다른 지정된 엔티티와 충돌하는 경우 두 엔티티의 결과 위치가 계산됩니다 (실제로는 그 이상을 수행하지만 아이디어는 얻음). NPCController는 AI이며 NPC 당 하나의 인스턴스입니다. NPC의 상황을 확인하고 이동할 위치를 결정한 다음 실제로 NPC를 이동시키는 MoveController로 경로를 푸시합니다. 컨트롤러는 우선 순위를 가지므로 순서를 미리 결정할 수 있습니다. PhysicController가 마지막으로 실행됩니다.

컨트롤러를 옹호하지만 유일한 “올바른”옵션은 아닙니다. 예를 들어 Entity 자체에 think () 메소드가있는 Cafu 엔진의 Entity 인터페이스를 기억하고 클래스의 사용자는 Entity에서 상속하고 think ()를 구현해야합니다. CompanyBot라는 파생 클래스를 기억합니다 (예제와 함께 제공됨) 그 방법으로 충돌 검사를하는 “생각”이라고 불리는 AI 코드도있을 것으로 예상 할 수 있습니다. NeoAxis 엔진 (마지막으로 살펴 봤지만)에는 AI와 물리가 엔티티와 분리되어 있습니다.

내가들은 컨트롤러 패턴이 있습니다. 어쩌면 당신은 그것을 검색해야 할 것입니다. 아마도 내가 여기서 이야기하고있는 것이 아니라 아마도 좋은 해결책처럼 들릴 것입니다.