계층적 유한 상태 머신
새로운 HFSM 생성하기
에디터의 탑 바에서 (+) 버튼을 클릭한 후 상태 머신 옵션을 선택합니다.

그러면 HFSM 파일을 저장하라는 메시지가 표시됩니다.
원하는 곳에 저장하세요.
이렇게 하면 비쥬얼 에디터에서 수행한 작업을 유지하는 데 사용되는 데이터 에셋이 생성됩니다.

노트: 지금 선택한 이름은 비쥬얼 에디터에서 수행한 작업을 컴파일할 때 추가로 생성된 다른 데이터 에셋의 이름이 됩니다.
이는 봇을 실제로 구동하는 데 사용되는 데이터 에셋이므로 제안된 이름을 선택할 수 있습니다.

파일을 저장하면 시작할 단일 NewState이 가진 메인 봇 SDK 윈도우가 나타나게 됩니다.
이제 이 초기 상태에 대해 자세히 살펴보겠습니다:

- 이 상태가 HFSM의 초기 상태임을 나타냅니다.
- 상태 이름
- 이 상태에서 나오는 전이 목록.
새로운 상태 생성하기
새로운 상태를 생성하기 위해서, 에디터 창에서 빈 공간을 마우스 오른쪽 버튼으로 클릭하고 Create New State를 선택합니다.


상태 편집하기
상태를 편집하려면 대상 상태를 마우스 오른쪽 버튼으로 클릭하고 Edit This State을 선택합니다.

여기서 상태 이름을 정의하고 전환 삭제/재지정할 수 있습니다.
PS: 전환 순서를 변경해도 우선순위는 변경되지 않습니다. 시각적 조정에만 사용됩니다. 이 자습서에 대한 우선순위에 대해 자세히 설명되어 있습니다.
변경 사항 저장하려면 엔터키를 누르거나 변경 사항을 무시하려면 Esc키를 누르세요.
상태 뷰 최소화하기
일반적으로 HFSM은 상태 및 전환의 측면에서 많은 양이 증가하므로 일부 HFSM의 흐름을 실제로 이해하기 어려울 수 있습니다.
모든 상태 노드에서 최소화 버튼을 클릭하여 전환 슬롯을 숨기고 해당 슬롯에서 선이 그려지는 방식을 변경하여 단순화된 보기를 사용할 수 있습니다.

이전 그리고 이후를 분석해보겠습니다.


두 가지 상태간의 전환 생성하기
두 상태 간의 전환을 시작하려면 먼저 모든 상태의 왼쪽/오른쪽 모서리에 있는 작은 원 중 하나를 클릭합니다.
그런 다음 다른 상태를 클릭하면 이 두 상태를 연결하는 새 전환이 생성됩니다.
다른 상태를 클릭하는 대신 빈 공간을 클릭하면 대상 상태를 즉시 생성하려는 경우 에디터가 생성 패널이 나타납니다.

새 전환을 생성할 때마다 어두운 색상이 나타나 전환이 아직 정의되지 않은것을 나타냅니다.
전환과 상호 작용하는 몇 가지 방법이 있습니다:
- 전환 중이면 마우스가 강조 표시됩니다.
- 전환을 왼쪽 클릭하면 전환 방향을 나타내는 작은 원이 전환 방향을 보여주게 됩니다.
- 전환을 두 번 클릭하면 해당 하위 그래픽에 들어가게 됩니다.
- 마우스 오른쪽 버튼 메뉴에서 전환 하위 그래픽에 들어가고, 전환을 뮤트 하거나 삭제할 수 있습니다.
결정 하위 그래프에 이미 생성된 노드를 분석해 보겠습니다:

이 노드가 전환을 실제로 정의하는 데 사용됩니다.
여기에는 네 가지 중요한 개념이 있습니다:
- 이 노드의 이름은 원시 상태와 대상 상태를 나타냅니다. 우클릭 메뉴를 사용하여 변경할 수 있으므로 의미 있는 이름으로 선택할 수 있으며, 위쪽에 표시되므로 어떤 상태인지 쉽게 파악할 수 있습니다.
- 첫 번째 슬롯은 이 전환을 평가할 때 고려해야 할 이벤트를 정의하는 데 사용됩니다.
- 두 번째 슬롯은 전환을 구성하는 Decision을 정의하는 데 사용됩니다.
- 세 번째 슬롯은 같은 노드에서 오는 모든 전환 간의 실행 순서를 정의하는 데 사용됩니다.
먼저 이 전환에 대한 간단한 결정을 정의해 보겠습니다.
이렇게 하려면 빈 공간을 마우스 오른쪽 단추로 클릭하면 패널에 만들 수 있는 가능한 결정이 표시됩니다.

간단하게 하기위해 TrueDecision을 선택합니다.
물론 이 결정의 결과는 언제나 사실입니다.

이 결정의 결과가 어디로 향할지 정의하는 아웃바운드 슬롯이 있습니다.
따라서 Result 슬롯의 한쪽에 있는 원을 왼쪽 버튼으로 클릭하여 의사 결정 슬롯에 연결합니다.

바로 그겁니다.
방금 가장 간단한 전환을 정의했습니다.
이를 통해 보트가 NewState에 있고 HFSM이 업데이트될 때마다 보트가 NewState1로 전송됩니다.
필드를 클릭하여 의사 결정 필드 값을 편집할 수 있습니다.

변경 사항 저장하려면 엔터키를 누르거나 변경 사항을 무시하려면 Esc키를 누르세요.
이제 아주 간단한 전환이 정의되었으니, 다시 탑 뷰로 돌아가서 어떻게 생겼는지 살펴보겠습니다.
탑바의 이동경로에 있는 Root 버튼을 클릭하여 상태 뷰로 돌아갈 수 있습니다.

또는 왼쪽 패널을 사용하여 상태를 탐색할 수 있습니다:

이제 그 전환이 더 이상 빨간색이 아니라는 것을 알 수 있습니다.
이는 올바른 전환임을 나타냅니다.

전환 우선순위 정의하기
전환이 두 개 이상 있는 상태에서는 먼저 평가될 상태를 정의할 수 있습니다.
이 순서를 정의하려면 우선순위 슬롯을 사용합니다. 클릭하여 값을 설정합니다.

상태 노드에서 전환의 우선순위를 보는것이 가능합니다.

상위 우선순위 상위에서 낮은 우선순위 순으로 전환이 평가됩니다.
이 우선순위로 어떤 전환을 먼저 확인해야 할지를 정의할 수 있습니다.
노트: 한 상태의 전환에 대해 정의된 우선순위는 다른 상태의 전환과 아무런 차이가 없습니다.
새로운 전환 생성하기
우리는 현재 두 상태 사이에 단 한 번의 전환만이 있습니다.
이 기능을 사용하면 어떤 상태에서도 다중 전환이 없기 때문에 우선순위 필드가 무용지물이 됩니다.
새로운 전환을 생성하려면 상태 하단에 마우스를 놓으면 나타나는 (+) 버튼을 클릭합니다.

그런 다음 첫 번째 전환과 마찬가지로 새로운 전환을 정의할 수 있습니다.

특별한 전환 유형
전환 집합
이러한 유형의 노드는 여러 전환을 그룹화하는 데 사용할 수 있습니다.
많은 상태에서 단일 전환 집합을 가리킬 수 있으므로 전환 집합을 재사용하는 것이 특히 유용합니다.
새 전환 집합을 만들려면 빈 공간을 마우스 오른쪽 버튼으로 클릭하고 새 전환 집합 만들기를 선택합니다.
그러면 상태 노드와 매우 유사한 노드가 생성됩니다. 노드는 정의되지 않은 단일 전환으로 시작되며, 마우스를 아래쪽 부분에서 맴돌면 많은 새 전환을 생성할 수 있습니다:

그리고 나서, 링크를 생성합니다.
다음은 예제입니다:

또한 상단 오른쪽 코너 버튼을 사용하여 전환 세트를 최소화할 수도 있습니다:

모든 전환
이러한 전환은 같은 계층 레벨의 모든 상태에서 수행해야 하는 전환을 정의할 때 매우 유용합니다.
PS: 계층에 대해서는 이 문서에서 자세히 설명합니다.
오른쪽 클릭 메뉴에서 새 전환을 만듭니다.
이제 모든 전환의 대상 상태를 정의합니다.

위의 샘플 이미지에서 해당 계층 수준의 모든 상태는 모든 노드에서의 전환을 고려합니다.
어떤 상태에서도 전환이 무시되는 상태 목록을 정의할 수 있습니다. 제외 목록 메뉴에서 선택합니다.

포털 전환
이 유형의 전환은 HFSM이 모든 레벨의 계층에서 다른 상태로 강제로 전환되도록 하기 위한 것입니다.
오른쪽 클릭 메뉴에서 새 포털 전환을 생성합니다.

이제 이 포털에서 HFSM을 사용할 상태를 정의해야 합니다.
드롭다운 메뉴를 클릭하여 선택합니다.
대상 상태의 이름은 사용자가 보유한 계층을 기반으로 합니다:

포털의 대상을 정의한 후에는 해당 포털에서 고려할 상태를 정의하기만 하면 됩니다.

복합 결정
단일 의사결정을 사용하여 전환을 정의하는 것 외에도 몇 가지로 구성된 결정을 작성할 수도 있습니다.
Bot SDK는 이미 3가지 논리적 결정을 통해 사용할 수 있습니다.
다음은 AND, OR 그리고 NOT 결정을 기반으로 구성된 결정 예제입니다.




이벤트
quantum_code 프로젝트에서 컴파일, 설정 등이 필요한 새 결정을 작성하지 않고 전환을 평가하려면 이벤트를 사용할 수 있습니다.
이벤트는 매우 간단한 방식으로 작동합니다. 이벤트가 트리거 될 때마다 현재 상태의 전환은 이벤트가 수신되고 있는지 확인합니다.
전환이 해당 이벤트를 수신할 경우 해당 이벤트가 수행됩니다.
코드 측면에서 이벤트를 트리거 하는 데 필요한 것은 다음과 같습니다:
아무 quantum_code 스크립트에서, 실행합니다:
C#
HFSMManager.TriggerEvent(f, &guy->Fields.HFSMAgent.Data, (Entity*)guy, "SomeEventName");
이 메서드 호출은 실행/결정 또는 시스템에서와 같은 다른 논리에 추가할 수 있습니다.
새로운 이벤트 생성을 하려면, 이벤트 세션의 좌측 패널에서 (+) 버튼을 클릭합니다:

그러면 새 이벤트를 생성하라고 표시됩니다.
이벤트를 두 번 클릭하여 이벤트 편집 또는 삭제를 열 수도 있습니다.
전환 하위 그래프에 이벤트를 배치하려면 이벤트를 끌어다 놓아야 합니다.
그런 다음 의사결정에 대해 수행한 작업과 유사하게 이벤트의 아웃바운드 슬롯을 전환 이벤트 인바운드 슬롯에 연결할 수 있습니다:

노트: 결정 사항과 달리 복합 이벤트 정의는 없으며 전환 시 연결된 하나 이상의 이벤트를 수락하지 않습니다.
단 하나의 이벤트로 정의된 결정으로 전환되는 것은 유효한 전환으로 간주됩니다.
또한 이벤트와 의사 결정을 모두 설정하여 전환을 정의할 수도 있습니다.
이 경우 이 전환은 이벤트가 트리거되고 같은 프레임에서 의사 결정 조건 결과가 True인 경우에만 발생합니다.

액션 정의하기
이제 상태 시스템 흐름(상태 및 전환 포함)을 생성하는 방법에 대해 논의했으므로 상태에 대한 동작을 정의하는 방법에 대해 살펴보겠습니다.
모든 상태에는 서브 그래프가 들어 있습니다.
이 하위 그래프에서 작업을 생성하거나 다른 상태의 흐름**(여기에 계층적 단어가 들어옴)**을 생성할 수 있습니다.
상태의 하위 그래픽에 접근하려면 아무 상태나 두 번 클릭합니다.
그런 다음 에디터가 하위 그래프를 표시하고 맨 위 표시줄에는 현재 계층의 깊이를 나타내는 경로 표시가 있습니다.
이러한 버튼을 사용하여 이전 계층 레벨로 이동할 수 있습니다.

상태의 하위 그래픽으로 들어갈 때 이미 정의된 노드가 있습니다: 액션 노드.

다음은 정의해야 할 세 가지 액션 목록입니다:
- On Enter 목록은 HFSM이 이 상태로 전환될 때 실행할 작업을 정의합니다.
- On Update 목록은 HFSM이 업데이트될 때마다 실행할 작업을 정의합니다(모든 프레임).
- On Exit 목록은 HFSM이 이 상태를 나갈 때 실행할 작업을 정의합니다.
이러한 작업 목록을 정의하려면 원하는 목록에서 화살표를 클릭한 다음 작업의 인바운드 슬롯을 클릭하거나 빈 공간을 클릭하여 새 작업을 즉시 생성합니다.

여기서 중요한 것은 필요한 만큼 많은 연결된 작업을 정의할 수 있다는 것입니다.
화살표 버튼을 사용하여 연결하기만 하면 됩니다.

원하는 대로 작업의 순서를 변경할 수 있습니다.
나중에 사용하기 위해 지금 삭제하지 않으려는 경우 분리된 액션 세트를 가질 수도 있습니다.

결정과 마찬가지로 필드를 클릭하여 작업 필드의 값을 정의할 수 있습니다.
변경 사항 저장하려면 엔터키를 누르거나 변경 사항을 무시하려면 Esc키를 누르세요.

뮤팅
HFSM 에디터에서, 3가지 유형의 뮤트가 있습니다:
뮤트 상태
뮤트 된 상태 노드는 컴파일 과정에서는 무시됩니다.
이렇게 하면 어떤 전환도 해당 상태로 이어지지 않으며 해당 액션/전환이 실행되지 않습니다.
PS.: 뮤트 기본 상태로 HFSM을 컴파일하면 오류가 발생합니다.
상태 노드를 뮤트 하기 위해서, 상태의 우측 클릭을 하고나서 "Mute/Unmute State"를 선택합니다.
뮤트 상태에서 투명하게 렌더링됩니다.

뮤트 전환
전환 라인에서 마우스 오른쪽 버튼으로 클릭하고 "Mute/Unmute Transition"를 선택하여 전환을 뮤트 할 수 있습니다.
컴파일 중에는 뮤트 된 전환이 무시됩니다.
공통 전환, 모든 전환, 전환 집합, 포탈로의 전환 등 모든 유형의 전환을 뮤트 할 수 있습니다.

뮤트 액션
작업 목록의 위치에 관계없이 모든 작업을 뮤트 할 수 있습니다.
뮤트 액션에 다음 액션이 포함된 경우, 뮤트 액션은 컴파일 중에 무시되며 체인에서 다음 액션만 실행됩니다.
또한 모든 작업 노드를 마우스 오른쪽 버튼으로 클릭하여 접근할 수도 있습니다.

계층구조
모든 상태의 하위 그래프에서 새 상태 및 전환 집합을 생성할 수 있습니다.
NewState 하위 그래프에서 AnotherState라는 새 상태를 생성한다고 가정해 보겠습니다.
이 작업을 수행하면 NewState가 부모이고 다른 상태는 자식이라는 두 작업 간에 관계가 생성됩니다.
부모와 자식 상태의 작업 및 전환이 모두 실행됩니다.
이렇게 하면 다른 상태 머신의 내부에 상태 머신을 캡슐화할 수 있습니다.
예를 들어, 3가지 레벨로 행동을 하는 보스가 있다면 매우 유용할 수 있습니다: 쉬운 모드에서 시작하여 HP의 절반에 도달하면 조금 더 힘들어집니다. 그리고 전체 체력의 10%만 유지하면 더욱 어려워집니다.
상단 그래프에 3개의 주요 상태를 만들 수 있으며 각 상태에는 보스의 난이도를 정의할 수 있는 자체 상태 시스템이 있습니다.
HFSM을 구성하는 방법을 개선하는 데 매우 유용합니다.
하위 상태를 만들려면 아무 상태의 하위 그래픽으로 이동하여 빈 공간을 마우스 오른쪽 버튼으로 클릭하고 새 상태 만들기 옵션을 선택합니다.
이렇게 하면 복잡한 계층 레벨을 가질 수 있으며, 이를 왼쪽 메뉴에서 시각화할 수 있습니다.

노트: 이러한 버튼들을 클릭하여 계층구조를 탐색할 수 있습니다.
또한 이러한 상태를 마우스 오른쪽 버튼으로 클릭하여 현재 그래프 보기에서 새 포털을 생성할 수도 있습니다.
중요: 또한 HFSM의 모든 계층 수준(기본 상태)에 대해 정의할 수도 있습니다. 이것은 부모 상태 사이를 전환할 때 입력되는 자식 상태를 정의하는 것입니다. 기본 상태를 정의하려면 상태 노드를 마우스 오른쪽 버튼으로 클릭하고 "기본 상태 만들기"를 선택합니다.
HFSM 컴파일하기
생성한 HFSM을 실제로 사용하려면 수행한 작업을 컴파일해야 합니다.
컴파일하는 것에는 다음 두 가지 옵션이 있습니다:

- 왼쪽 버튼은 현재 열려 있는 문서만 컴파일하는 데 사용됩니다.
- 오른쪽 버튼은 프로젝트에 있는 모든 AI 문서를 컴파일하는 데 사용됩니다.
HFSM 파일의 위치는 다음과 같습니다: "Assets/Resources/DB/CircuitExport/HFSM_Assets".

봇에서 사용하도록 AI를 설정하기
마지막으로 생성된 AI를 사용하려면 컴파일된 에셋을 참조하기만 하면 됩니다.
GUID를 기반으로 자산을 로드하여 작업을 수행하거나 Asset Link를 생성하여 원하는 AI 에셋을 가리킬 수 있습니다.

HFSM 코딩
DSL의 관점에서 볼 때 새로운 HFSMAgents를 생성하는 두 가지 주요 옵션이 있습니다.
- HFSMAgent를 필드 또는 엔티티의 구성 요소로 사용할 수 있습니다.
- 엔티티를 가질 필요 없이 구조체나 글로벌 스페이스에서 선언할 수 있습니다.
게임 흐름 만들기, 게임 시작 시 수행되는 액션 정의, 게임의 현재 상태 변경 시기 정의 등과 같은 엔티티 범위를 벗어나는 작업을 HFSM이 수행하도록 할 수 있기 때문에 이 사실을 아는 것이 중요합니다.
먼저, 예를 들어 HFSMAgent를 엔티티 필드에 추가합니다.
C#
entity MyEntity[6]{
use Transform2D;
use DynamicBody;
use Prefab;
fields{
player_ref Player;
HFSMAgent HFSMAgent;
}
}
그런 다음 애플리케이션에 적합한 모든 시점에서 그 엔티티의 HFSMManager.Init 메소드를 호출해야 합니다.
C#
HFSMManager.Init(f, &myEntity->Fields.HFSMAgent.Data, (Entity*)guy, data.HFSMRoot, aiContext);
파라미터는 다음과 같습니다:
- 프레임
- 모든 HFSMAgent에 포함되어 있는 HFSMData의 포인터
- 대상 엔티티에 대한 포인터
- 모든 HFSMAgent에 포함되어 있는 HFSMRoot
- 있는 경우 AIContext
이제 엔터티의 HFSMAgent가 초기화되었으므로 필요할 때마다 업데이트 메서드를 호출하면 됩니다:
C#
HFSMManager.Update(f, f.DeltaTime, &guy->Fields.HFSMAgent.Data, (Entity*)guy, aiContext);
이것은 HFSM이 초기 상태의 데이터를 실행하고 다른 상태로 작업 및 전환을 수행합니다.
이를 통해 AI는 이미 Visual Editor에서 생성한 흐름을 따라야 합니다.
액션과 결정 코딩하기
이미 본 것과 같이 그 에디터는 이미 몇 가지 미리 정의된 액션 및 결정이 있습니다.
그것들은 개발자가 시작할 수 있도록 만들어졌습니다.
프로젝트에는, 특정 액션 및 결정을 구현해야 할 필요가 있습니다.
어떻게 하는지 살펴보겠습니다.
새로운 액션을 생성하기 위해서는, quantum_code 솔루션을 열어야 합니다.
quantum.state 프로젝트에서, AIAction
추상 클래스에서 상속된 클래스를 생성할 수 있습니다.
이것을 수행할 때, HFSMManager.Update
메소드를 통해 에이전트가 업데이트될 때마다 호출되는 Update
메소드를 구현해야 합니다.
새로운 클래스는 [Serializable]
로 마킹을 해주어야 합니다.
C#
namespace Quantum
{
[Serializable]
public class IdleAction : AIAction
{
public override unsafe void Update(Frame f, Entity* e, AIContext c)
{
// insert the action code here
}
}
}
나만의 결정의 생성하는 것은, 매우 유사합니다.
하지만, AIAction
클래스에서 상속을 받는 새로운 클래스를 생성하는 대신, HFSMDecision
추상 클래스로부터 상속을 받도록 작성해 줍니다.
또한 Update
메소드를 가지고 있는 대신, Decide
메소드를 구현해 주어야 합니다.
필요에 따라 true
/false
을 리턴해줄 때 사용합니다.
이 클래스들도 [Serializable]
로 마킹이 되어야 합니다.
C#
namespace Quantum
{
[Serializable]
public class TrueDecision : HFSMDecision
{
public override unsafe bool Decide(Frame frame, HFSMData* fsm, Entity* entity, AIContext context)
{
// insert the decision code here
return true;
}
}
}
필드값 정의하기
앞서 설명한 대로 개발자가 값을 정의할 수 있도록 Visual Editor 노드에 표시되는 액션 및 결정에 필드를 선언할 수 있습니다.
이러한 값을 설정하는 더 간단한 방법은 필드를 클릭하고 값을 즉시 할당하는 것입니다. 그러나 다음과 같은 다른 옵션이 있습니다.
- Blackboard 노드를 사용합니다.
- 상수 노드를 사용합니다.
Blackboard 노드는 Blackboard 문서에 이미 설명되어 있으므로 상수 노드에 대해 살펴보겠습니다.
상수 패널
왼쪽 패널에서 상수를 정의하고 사용할 수 있습니다.
상수를 정의한 후에는 상수 노드를 캡처하여 액션 및 결정의 인바운드 슬롯에 연결할 수 있습니다. 단일 상수 노드를 여러 번 입력으로 사용할 수 있으므로 동시에 여러 필드를 더 쉽게 정의할 수 있습니다.
상수의 또 다른 중요한 측면은 설정 메뉴에서 해당 값이 변경될 때마다 해당 상수에서 생성된 모든 노드가 그에 따라 업데이트되므로 HFSM의 여러 부분에서 값을 정의하고 나중에 값을 변경할 수 있습니다.
왼쪽 메뉴를 사용하여 새 상수를 정의하고 상수 탭에서 (+) 심볼을 클릭합니다.

그리고 나서 Name
, Type
, Default Value
을 선택하고 저장합니다. 이제 상수가 정의되어 있으면 그래프 보기로 끌어다 놓고 인바운드 슬롯에 연결할 수 있습니다.

AI 상수 데이터 에셋
상수가 선언된 문서를 컴파일할 때마다 AIConstantDataAsset
유형의 새 데이터 에셋이 생성됩니다. HFSM 에셋에 중첩되며 이름은 "HFSM-이름 + GraphVars"가 됩니다.

이것은 Visual Editor에 생성된 상수의 이름/값들을 저장하는 데 사용되는 데이터 에셋입니다. HFSM 루트 자산에서 이미 참조하고 있습니다.

즉, 코드에서 상수 에셋을 얻고 다음 작업을 수행하여 상수 값을 참조할 수 있습니다.
C#
myEntity->Fields.HFSMAgent.Data.Root.Constants.Instance.GetFP(string key);
그러나 상수 값을 저장하고 읽는 또 다른 선택적인 방식은 AI Context에서 하는 것입니다.
AIContext
SDK(HFSM 및 GOAP )를 모두 사용하는 모든 AI에 대한 컨텍스트를 지정하기 위해 기본적으로 2개의 상수 파일에 대한 참조를 저장할 수 있는 클래스인 AIContext가 있습니다. 다음은 AIContext에서 확인할 수 있는 내용입니다:
- AI당 필드인
Constants
필드는 동일한 HFSM/GOAP을 가진 모든 에이전트가 사용할 상수 자산을 참조하는 것을 의미합니다. 일반적으로 위에서 언급한 컴파일 프로세스에서 생성된 상수 에셋을 참조합니다. Config
필드는 엔티티당 필드로, 동일한 HFSM/GOAP을 사용 하더라도 다른 엔티티에 대해 서로 다른 상수 에셋을 참조하는 데 사용할 수 있습니다. 아주 간단한 샘플은 동일한 HFSM을 사용하지만 Config 필드와 다른 속도를 가진 두 개의 고블린 엔티티를 갖는 것입니다.- 이러한 필드들은
AIConstantDataAsset
유형의 에셋을 참조할 수 있습니다. 컴파일 프로세스에서 자동으로 생성된 에셋 또는 마우스 오른쪽 버튼 메뉴Create/Quantum/Assets/AIConstantData
에서 수동으로 생성한 에셋을 참조할 수 있습니다. AIContext
는 부분 클래스로, 이 클래스를 확장하여 더 많은 사용자 지정 데이터를 결정 및 작업에 전달할 수 있습니다.- 런타임에 참조되는 에셋을 변경할 수 있으므로 원하는 대로 구성을 교환할 수 있습니다.
코드 측면에서 AIContext
는 Init
, Update
, Action.Update
그리고 Decision.Decide
와 같은 코어 Bot SDK 메소드의 일부 파라미터 중 하나입니다.
컴파일 프로세스가 완료되면 상수 자산이 HFSMRoot에서 참조됩니다.
C#
HFSMRoot.Instance.Constants
또한 HFSMAgent에는 구성 에셋을 참조하는 데 사용할 수 있는 에셋 참조 필드가 있습니다:
C#
myEntity->Fields.HFSMAgent.Config.Asset;
이때 전달할 컨텍스트 정보가 없는 경우 컨텍스트 매개 변수로 null을 전달할 수 있습니다.
C#
HFSMManager.Update(f, f.DeltaTime, &myEntity->Fields.HFSMAgent.Data, (Entity*)myEntity, null);
그러나 Visual Editor에서 이미 상수를 사용 중이거나 컨텍스트로 전달할 정보가 이미 있는 경우 AIContext
클래스의 인스턴스를 생성하고 유지한 후 필요할 때마다 HFSM에 전달합니다.
C#
AIContext context = new AIContext();
// The Constants field comes from the HFSMRoot
context.Constants = data.HFSMRoot.Instance.Constants.Instance;
// The Config field needs to be filled by you
// You can either do a DB search directly, or pick it from some pre-defined field
// ...such as the HFSMAgent.Config
context.Config = guy->Fields.HFSMAgent.Config.Asset;
AIParam
작업 결정 및 필드의 값을 정의하는 방법은 다르므로 코드에 대해 이러한 값을 읽는 방법도 다릅니다. 이 때문에 개발자가 소스 유형을 서로 변경해야 하는 경우(즉, Blackboard 노드에서 상수 노드로 변경) 소스 코드도 변경해야 합니다.
그런데 소스 유형을 변경하는 것이 유용할 수 있는 이유는 무엇입가요?
- 단순성을 위해 값을 수동으로 정의할 수 있습니다.
- 런타임 중에 값이 변경될 수 있는 경우 Blackboard에 저장될 수 있으므로 Blackboard 노드를 사용하여 값을 정의합니다.
- 값이 변경되지 않지만 노드에서 가져와야 하는 경우 그래프의 유연성을 높이려면 상수 노드를 사용하여 값을 정의합니다.
AIParam
은 이런 상황을 돕기 위해 만들어진 타입입니다. 하지만, 그 용도에 대해 배우기 전에, 코드들 간의 차이를 빨리 분석해보도록 하겠습니다.
일부 필드의 값이 Visual Editor에서 수동으로 정의된 경우 이 값을 읽는 코드는 간단하고 간단합니다:
C#
public Int32 MyInteger;
Log.Info(MyInteger);
이제 이 값이 Blackboard 노드에서 온 경우 다음을 수행합니다:
C#
var value = blackboardComponent->Board.GetValue("someKey");
Log.Info(value);
따라서 Visual Editor에서 값 소스가 변경될 때 코드를 변경할 필요가 없도록 필드에 AIParam
타입을 사용합니다. 주요 특징은 다음과 같습니다.
- 블랙보드, 상수 및 구성을 수신하는
Resolve
메소드를 가지고 있습니다. 이 메소드는 필드 값의 출처가 무엇인지 파악하여 값을 직접 반환하거나(필드가 수동으로 정의되었을 때) Blackboard/Configs에서 값을 반환하여 이미 올바른 값을 반환합니다. 따라서 필요한 시간만큼 값 소스 타입을 변경할 수 있으며, 이 코드는 해당 유형을 읽는 데 사용됩니다:
C#
public AIParamInt MyAIParam;
var value = MyAIParam.Resolve(frame, blackboardComponent, Constants, Config);
Log.Info(value);
- 현재 8가지 가능한 타입이 있습니다:
C#
AIParamInt, AIParamBool, AIParamByte, AIParamFP, AIParamFPVector2, AIParamFPVector3, AIParamString, AIParamEntityRef
Visual Editor 에서
액션 및 결정에 public AIParam
이 선언되면 Visual Editor에 표시되며 수동으로 또는 Blackboard/Constant 노드에서 해당 값을 정의할 수 있습니다. 예를 들어 public AIParamInt IncreaseAmount
를 고려하면 다음과 같습니다.

디버거
Bot SDK에는 자체 디버깅 도구가 함께 제공됩니다. 그러면 개발자가 런타임에서 모든 HFSM 에이전트를 클릭하고 Visual Editor에 강조 표시된 최신 에이전트 흐름을 볼 수 있습니다. 다음은 Bot SDK 샘플 프로젝트에서 작업하는 디버깅 도구의 샘플입니다.

위의 gif에서 볼 수 있듯이, 에이전트의 현재 상태는 무엇이며, 이러한 상태로 이어졌던 가장 최근의 세 가지 전환은 어떤 것인지 알 수 있습니다.
또한 계층 보기에서 현재 상태를 검사할 수도 있습니다. 화살표가 있는 상태는 HFSM이 현재 해당 상태에 있음을 나타냅니다. 이 기능은 현재 에이전트가 계층에 얼마나 깊이 있는지 확인하기 위해 시각적 그래프를 탐색할 필요가 없으므로 유용합니다.

디버거 사용하기
다음은 프로젝트에서 디버거를 사용하기 위한 절차입니다.
필드 또는 구성요소에
HFSMAgent
가 있는 Quantum 엔티티를 나타내는 프리팹을 선택합니다.거기에
HFSMDebugComponent
를 추가합니다.Visual editor에서, 화면 오른쪽 상단 모서리에 있는 버그 아이콘을 클릭합니다. 아이콘이 녹색으로 표시될 때 디버깅은 active입니다.

DeterministicConfig
파일에서,Expose Verified Status In Simulation
을true
로 설정합니다;
PS: 디버거를 사용하지 않는 동안에는 이 기능을 사용할 필요가 없습니다!

- 런타임 동안 Bot SDK 창이 열린 상태에서 계층의 에이전트인 아무 게임 객체를 선택합니다. 바로 그거예요! 디버깅이 이미 작동하고 있어야 합니다.
PS: 현재, 엔티티에 연결되지 않은 에이전트(예: DSL 글로벌에 있는 에이전트)는 디버깅할 수 없습니다. 앞으로 출시될 버전에서 추가될 예정입니다.
Visual Editor 주석
Visual Editor에 주석을 추가할 수 있습니다. 이렇게 하려면 노드(상태/작업/결정/조건 등)를 선택하고 G를 눌러 주석 영역을 추가합니다. 그런 다음 "Comment" 헤더 텍스트를 클릭하고 원하는 대로 변경합니다. 둘 이상의 노드에 주석을 추가할 수도 있습니다. 노드를 두 개 이상 선택하려면 Windows OS에서 "Ctrl" 키를 누르고 Mac OS에서 "Command" 키를 누릅니다.


프레임에서 발생하는 것
Bot SDK에서, 메인 엔트리 포인트는 다음과 같습니다:
HFSMManager.Update
, 에이전트를 업데이트하기 위해 지속적으로 호출됩니다.HFSMManager.Init
, 에이전트를 초기화하는 데 사용됩니다.HFSMManager.TriggerEvent
, 트리거 된 이벤트를 고려하여 전환 점검을 강제합니다.
이러한 방법이 호출될 때 프레임에서 발생하는 상황을 더 잘 시각화할 수 있도록 하기 위해 다음의 흐름 그래프가 있습니다.
