컴포넌트 기반 게임에서 엔티티 상태 및 애니메이션을 업데이트하는 방법은 무엇입니까?


10

학습 목적으로 (그리고 나중에 일부 게임에서 사용하기 위해) 구성 요소 기반 엔터티 시스템을 설계하려고하는데 엔터티 상태를 업데이트하는 데 문제가 있습니다.

구성 요소 사이에 종속성을 방지하기 위해 구성 요소 안에 update () 메서드를 원하지 않습니다.

현재 내가 생각하는 것은 구성 요소에 데이터가 있고 시스템이 구성 요소를 업데이트한다는 것입니다.

따라서 Transform, Movement, State, Animation 및 Rendering 구성 요소가있는 일부 엔티티 (예 : player, enemy1, enemy2)가있는 간단한 2D 게임을 가지고 있다면 다음과 같이 생각합니다.

  • 모든 이동 구성 요소를 이동하고 상태 구성 요소를 업데이트하는 이동 시스템
  • 애니메이션 구성 요소 (애니메이션 구성 요소에는 각 상태에 대해 하나의 애니메이션 (즉, 프레임 / 텍스처 세트)가 있어야 함)를 업데이트하고 업데이트하는 렌더링 시스템은 현재 상태 (예 : 점프, 이동 _ 왼쪽 등)에 해당하는 애니메이션을 선택하는 것을 의미합니다. 프레임 인덱스 업데이트). 그런 다음 RenderSystem은 각 엔티티 애니메이션의 현재 프레임에 해당하는 텍스처로 Render 구성 요소를 업데이트하고 모든 것을 화면에 렌더링합니다.

Artemis 프레임 워크와 같은 구현을 보았지만이 상황을 해결하는 방법을 모르겠습니다.

내 게임에는 다음과 같은 엔티티가 있다고 가정 해 봅시다. 각 엔티티에는 상태 세트와 각 상태마다 하나의 애니메이션이 있습니다.

  • 플레이어 : "유휴", "moving_right", "점프"
  • enemy1 : "moving_up", "moving_down"
  • enemy2 : "moving_left", "moving_right"

각 엔터티의 현재 상태를 업데이트하기 위해 가장 많이 사용되는 방법은 무엇입니까? 내가 생각할 수있는 유일한 것은 각 엔티티 그룹과 별도의 State 및 Animation 구성 요소에 대해 별도의 시스템을 가지고 있으므로 PlayerState, PlayerAnimation, Enemy1State, Enemy1Animation ... PlayerMovementSystem, PlayerRenderingSystem ...을 갖습니다. 구성 요소 기반 시스템의 목적을 깨뜨립니다.

보시다시피, 나는 여기서 잃어 버렸으므로 도움을 주시면 대단히 감사하겠습니다.

편집 : 내가 의도 한대로이 작업을 수행 할 수있는 솔루션은 다음과 같습니다.

statecomponent 및 animationcomponent를 모든 엔터티에 사용할 수 있도록 일반으로 만듭니다. 여기에 포함 된 데이터는 재생되는 애니메이션 또는 사용 가능한 상태와 같은 항목을 변경하기위한 수정 자입니다. – 바이트 56

이제이 두 구성 요소를 충분히 일반적인 방식으로 디자인하여 재사용 할 수 있도록 설계하려고합니다. 각 상태에 대한 UID가 있고 (예 : 걷기, 달리기 ...) 맵에 애니메이션을이 식별자로 키가 지정된 AnimationComponent에 저장하는 것이 좋은 솔루션일까요?


나는 당신이 이것을 본다고 가정합니다 : 엔티티 또는 구성 요소의 상태 변경 ? 질문이 근본적으로 다른 질문입니까?
MichaelHouse

@ Byte56 예, 몇 시간 전에 읽었습니다. 당신이 제안한 해결책은 내가 여기에 노출 한 아이디어와 비슷합니다. 그러나 StateComponent와 AnimationComponent가 시스템의 모든 엔티티에 대해 동일하지 않을 때 문제가 발생합니다. 해당 시스템을 가능한 상태 및 애니메이션이 동일한 엔티티 그룹을 처리하는 더 작은 시스템으로 분할해야합니까? (더 나은 설명을 위해 내 원래 게시물의 마지막 부분을 참조하십시오)
miviclin

1
당신은 확인 statecomponent하고 animationcomponent일반적인만큼 모든 개체에 사용할 수 있습니다. 여기에 포함 된 데이터는 재생되는 애니메이션 또는 사용 가능한 상태와 같은 항목을 변경하기위한 수정 자입니다.
MichaelHouse

의존성에 대해 이야기 할 때 데이터 의존성 또는 실행 순서 의존성을 의미합니까? 또한 제안 솔루션에서 MovementSystem은 이제 무언가 움직일 수있는 다른 모든 방법을 구현해야합니까? 이것은 컴포넌트 기반 시스템의 아이디어를 깨뜨리고있는 것 같습니다 ...
ADB

@ADB 데이터 의존성에 대해 이야기하고 있습니다. 애니메이션을 업데이트하려면 (예 : move_right 애니메이션에서 move_left 애니메이션으로 변경) 엔터티의 현재 상태를 알아야하며이 두 구성 요소를보다 일반적인 것으로 만드는 방법을 알 수 없습니다.
miviclin

답변:


5

IMHO Movement구성 요소는 현재 상태 ( Movement.state)를 유지해야 하며 Animation구성 요소는 상태 ID를 애니메이션에 대한 간단한 조회를 통해 Movement.state(현재 Animation.animationOP의 끝에서 제안 된대로) 현재 애니메이션의 변경 사항을 관찰 하고 업데이트 해야합니다 (). 분명히 이것은 Animation의지 할 것입니다 Movement.

대체 구조 는 기본적으로 모델 뷰 컨트롤러 (이 경우 상태 애니메이션 이동) StateAnimation관찰 및 Movement수정 하는 일반 구성 요소 를 갖는 것 입니다.

또 다른 대안은 상태가 변경 될 때 엔티티가 구성 요소에 이벤트를 전달하도록하는 것입니다. Animation이 이벤트를 듣고 그에 따라 애니메이션을 업데이트합니다. 종속 버전이 더 투명한 디자인이라고 주장 할 수 있지만 이는 종속성을 제거합니다.

행운을 빕니다.


따라서 애니메이션은 상태를 관찰하고 상태는 움직임을 관찰합니다 ... 의존성은 여전히 ​​있지만 시도해 볼 수 있습니다. 마지막 대안은 다음과 같습니다. 움직임이 엔티티에 변경 사항을 알리고 엔티티가 이벤트를 State에 디스패치 한 다음 State 및 Animation에 대해 동일한 프로세스가 반복됩니까? 이 접근 방식이 성능에 어떤 영향을 줄 수 있습니까?
miviclin

첫 번째 경우 : Movement제어 State (준수되지 않음). 마지막 경우 : 그래 Movement할 것 entity.dispatchEvent(...);정도 및 이벤트의 유형을 듣고 다른 모든 구성 요소를 받게됩니다. 성능은 순수한 메소드 호출보다 나쁘지만 그리 많지는 않습니다. 예를 들어 이벤트 객체를 풀링 할 수 있습니다. Btw, 엔터티를 "이벤트 노드"로 사용할 필요가 없으며 전용 "이벤트 버스"도 사용할 수 있으므로 엔터티 클래스를 완전히 배제 할 수 있습니다.
Torious

2

STATE가 애니메이션에서만 사용되는 경우 문제에 대해 다른 구성 요소에 노출 할 필요조차 없습니다. 두 번 이상 사용하면 노출해야합니다.

설명하는 구성 요소 / 하위 시스템 시스템은 구성 요소 기반보다 계층 구조가 더 느립니다. 결국 구성 요소로 설명하는 것은 실제로 데이터 구조입니다. 그것은 그것이 나쁜 시스템이라는 것을 의미하지는 않습니다. 단지 그것이 시스템 기반 접근 방식에 너무 잘 맞지 않는다고 생각합니다.

앞서 언급했듯이 구성 요소 기반 시스템에서 종속성은 큰 문제입니다. 그것을 처리하는 다른 방법이 있습니다. 일부는 각 구성 요소가 종속성을 선언하고 엄격한 검사를 수행해야합니다. 다른 사람들은 특정 인터페이스를 구현하는 구성 요소를 쿼리합니다. 여전히 다른 구성 요소는 각 구성 요소를 인스턴스화 할 때 종속 구성 요소에 대한 참조를 전달합니다.

사용하는 방법에 관계없이 컴포넌트 컬렉션의 역할을하는 일종의 GameObject가 필요합니다. 게임 오브젝트가 제공하는 기능은 매우 다양 할 수 있으며 자주 사용하는 데이터를 게임 오브젝트 레벨로 푸시하여 컴포넌트 간 종속성을 단순화 할 수 있습니다. Unity는 예를 들어 변환을 통해 모든 게임 오브젝트에 하나를 갖도록합니다.

여기, 당신이 다른 게임 객체에 대한 서로 다른 상태 / 애니메이션의 요청 문제에 관한 것은 무엇을 내가 할 것입니다. 첫째, 구현 의이 단계에서 너무 화려하지는 않습니다. 지금 작동하기 위해 필요한 것을 구현 한 다음 필요에 따라 종과 휘파람을 추가하십시오.

먼저 'State'구성 요소 인 PlayerStateComponent, Enemy1State, Enemy2State로 시작하겠습니다. 상태 구성 요소는 적절한 시간에 상태 변경을 처리합니다. State는 거의 모든 오브젝트가 가질 수있는 것이므로 GameObject에 상주 할 수 있습니다.

그런 다음 AnimationCompoment가 있습니다. 여기에는 상태에 맞춰진 애니메이션 사전이 있습니다. update ()에서 상태가 변경되면 애니메이션을 변경하십시오.

찾을 수없는 프레임 워크 구축에 대한 훌륭한 기사가 있습니다. 도메인에 경험이 없으면 하나의 문제를 선택하고 현재 문제를 해결하는 가장 간단한 구현을 수행해야한다고 말했다 . 그런 다음 다른 문제 / 사용 사례를 추가하고 진행하면서 프레임 워크를 확장하여 유기적으로 성장합니다. 나는 특히 새로운 개념으로 작업 할 때 그 접근법을 정말 좋아합니다.

내가 제안한 구현은 순진하지만 더 많은 유스 케이스를 추가함에 따라 가능한 개선 사항이 있습니다.

  • GameObject 변수를 사전으로 교체하십시오. 각 구성 요소는 사전을 사용하여 값을 저장합니다. (충돌을 올바르게 처리해야합니다 ...)
  • 대신 일반 값의 사전을 참조로 바꿉니다. class FloatVariable () {public value [...]}
  • 다중 상태 컴포넌트 대신 가변 상태 머신을 빌드 할 수있는 일반 StateComponent를 작성하십시오. 키 누름, 마우스 입력, 변수 변경 (위의 FloatVariable에 묶을 수 있음)과 같이 상태를 변경할 수있는 일반적인 조건 세트가 있어야합니다.

이 접근법은 효과가 있으며 1 년 전에 비슷한 것을 구현했지만 문제는 거의 모든 구성 요소가 다른 구성 요소에 의존하므로 유연성이 떨어지는 것입니다. 또한 가장 일반적인 컴포넌트 (예 : 변환, 렌더링, 상태 ...)를 엔티티로 푸시하는 것에 대해 생각했지만 컴포넌트 중 일부가 엔티티에 연결되어 있고 일부 엔티티가 필요하지 않을 수 있으므로 컴포넌트의 목적을 위반한다고 생각합니다. 그렇기 때문에 로직 업데이트를 담당하는 시스템으로 다시 설계하려고 시도하므로 구성 요소는 자체 업데이트하지 않으므로 서로에 대해 아무것도 알지 못합니다.
miviclin

0

ADB의 답변 외에도 http://en.wikipedia.org/wiki/Dependency_injection을 사용 하면 구성 요소를 생성자에 대한 참조로 전달하여 많은 구성 요소를 구성해야 할 때 도움이됩니다. 분명히 그들은 여전히 ​​서로 의존 할 것입니다 (코드베이스에 필요한 경우). 종속성이 설정되고 코드의 나머지 부분이 의존성에 대해 알 필요가없는 한곳에 모든 의존성을 둘 수 있습니다.

이 접근 방식은 인터페이스를 사용하는 경우에도 효과적입니다. 각 구성 요소 클래스는 필요한 것 또는 등록해야 할 위치를 요청하고 종속성 주입 프레임 워크 (또는 일반적으로 응용 프로그램을 설정 한 장소, 일반적으로 앱) 만 누가 누가 필요한지를 알고 있기 때문에 .

간단한 시스템의 경우 DI 또는 깨끗한 코드를 사용하지 않고 벗어날 수 있습니다. RenderingSystem 클래스는 정적이라고 부르거나 최소한 각 구성 요소에서 사용할 수 있어야하는 것처럼 들리므로 서로 의존하고 변경하기가 거의 불가능합니다. 보다 깨끗한 접근 방식에 관심이 있다면 위의 DI wiki 링크의 링크를 확인하고 Clean Code에 대해 읽으십시오 : http://clean-code-developer.com/


구성 요소가 서로 의존하는 시스템이 이미 있습니다. 나는 거기에 의존성 주입을 많이 사용했으며 깊은 계층 구조보다 선호하지만 구성 요소 커플 링을 피하기 위해 새로운 계층 구조를 만들려고합니다. 정적으로 아무것도 부르지 않을 것입니다. 모든 시스템에 액세스 할 수있는 ComponentManager가 있고 (모든 시스템에는 참조가 있어야 함) RendererSystem은 구성 요소 관리자에서 모든 애니메이션 구성 요소를 가져 와서 각 애니메이션의 현재 상태를 렌더링합니다.
miviclin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.