엔터티 시스템의 많은 이동원


9

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

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

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

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

전통적인 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
MoveBy기능 과 같은 소리 는 일종의 속도일까요? 당신이 올바른 길을 가고있는 것 같습니다. 두 번째 질문에는 엔터티 / 구성 요소 시스템의 다양한 구현이 있습니다. 내 대답에 설명 된 것은 주어진 유형의 구성 요소를 하나만 가질 것입니다.
MichaelHouse

일종의, 그러나 차이점은이 속도는 한 번에 한 번만 유효하며, 그 중 많은 수가 한 번에 함께 합성 될 수 있다는 것입니다. 나는 단지 약간의 안심이 필요하다고 생각합니다. 지난 몇 년 동안 같은 프로젝트에서 생산 속도를 떨어 뜨린 과거의 게임에 대해 엄격한 (거의 거의) OO였습니다. . 그건 그렇고 다른 게시물에 큰 대답은 몇 가지 일을 정리하는 데 도움이
Sticky

나는 이것을 좋아한다 : 나는 PlayerClickComponent와 AIInputComponent (또는 시스템)을 가지고있어 MobileBehaviorComponent에게 키보드 클릭시 또는 AI가 모바일이 어딘가로 움직여야한다고 생각하고, MobileBehaviorComponent는 어딘가로 움직여야한다고 저장한다 (모바일 동작을 위해 FSM이 있음) 그리고 어떤 시스템은 그것을 움직일 것입니다. Transform, Model, Light, Mob와 같은 더 높은 수준의 구성 요소로 인해 입도가 너무 커져 모든 것이 잘 작동합니다. 또한 구성 요소를 제거 할 필요가 없었습니다. 게임 개체를 설명하는 것으로 생각하면 사라질 수 없습니다.
Kikaimaru

이 특정 MoveBy 예제는 예제 일뿐입니다. 문제는 당신이 어떻게 그런 것들을 합성하는지에 관한 것이 었습니다. 구체적으로 '5 초 안에 x = 5 및 y = 6으로 이동', '10 초 안에 x = 10 y = 2로 이동 '으로 말해야하는 경우, 이렇게하는 방법은 무엇입니까?
Sticky

"복합"이란 무엇을 의미합니까? 속도 추가처럼? 당신이 합성 move x by 10 in 2 seconds하고 move x by -10 in 2 seconds엔티티가 완벽하게 여전히 서 있다면 ?
Tom Dalling

답변:


6

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

  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 기능을 쉽게 정의 할 수 있습니다. 또한 엔터티 시스템 구성 요소 목록을 너무 세분화하지 않고 간결하게 유지할 수 있습니다.


1

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

예를 들어 : 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와 물리가 엔티티와 분리되어 있습니다.

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


그것은 기본적으로 우리가 이미 가지고있는 OO 디자인입니다. 파생물 (캐릭터, 몬스터) 등이있는 엔티티로 거의 2 년 동안이 게임에서 풀 타임으로 일한 우리 팀을 이끌고 있으며 모두가 마음대로 물건을 변경하면 끔찍하고 끔찍합니다. 코드베이스-새로운 기능을 제공하는 데 시간이 많이 걸리기 시작했습니다. 엔터티 시스템 아이디어는 것 같다 정확하게 당신이 질문의 상단에있는 링크를 직접 읽어들이 :) 당신을 도울 수 있는지 확인해야합니다, 당신의 대답은 매우 관련이없는 동안 내가 지금, 무엇을 찾고 있어요
끈적 끈적한

@Sticky 필자는 구성 요소로 만든 노드 시스템과 엔티티가 덜 진화 된 버전과 같은 제안 된 컨트롤러 접근 방식과 다른 필요한 시스템을 나타내는 영리한 방법이라는 것을 인정해야합니다. 당신은 정말 내 대답이 필요하지 않습니다.
Hatoru Hansou

걱정 마. OO 방식은 장점이 있지만 상황이 추악하고 빠릅니다.
Sticky
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.