목표 지향적 실행 계획
새로운 GOAP 생성하기
탑 메뉴를 이용하여, 새로운 GOAP를 생성할 수 있습니다.

새로운 작업 생성하기
빈 공간에서 마우스 오른쪽 버튼을 클릭하면 새로운 작업을 생성할 수 있습니다.
작업에는 조건 및 효과 세트가 있습니다.
그것들은 게임의 월드 상태와 직접적으로 관련이 있습니다.
quantum_code 솔루션에 정의된 월드 상태 플래그 세트를 가질 수 있습니다.
- 조건은 해당 조건이 현재 월드 상태와 일치할 경우 작업을 수행해야 함을 지정합니다.
- 효과는 작업이 완료된 후 무엇이 세계 상태를 변경할 것을 지정합니다.
다음은 상태/효과 정의 없이 만들 수 있는 보다 간단한 작업입니다:

작업 이름은 우측 클릭하고 Edit Task Settings 을 선택하여 변경할 수 있습니다.
변경사항을 적용하기 위해서 엔터를 누르거나 변경사항을 취소하려면 Esc를 누릅니다.

조건/효과 지정하기
작업에 대한 조건/효과를 지정하려면 왼쪽/오른쪽 버튼을 클릭하고 추가할 월드 상태 플래그를 선택합니다.
선택하지 않은 것은 무시됩니다.

모든 작업에 새 월드 상태 플래그를 추가하면 True로 처리됩니다.
조건의 경우, 이 플래그가 월드 상태에서 True로 설정되었는지 확인할 수 있습니다.
효과에 따라, 월드 상태에서 플래그를 참으로 설정합니다.
이러한 값을 토글 하려면 왼쪽 플래그 옆에 있는 작은 녹색 원을 클릭하면 빨간색으로 바뀝니다.

여러 조건 및 효과를 추가하고 원하는 방식으로 값을 전환할 수 있습니다:

따라서 GOAP에는 다음과 같은 여러 가지 작업이 정의되어 있으며 다양한 조건 및 효과 세트가 있습니다.

또한 계획 절차 중에는 무시되도록 태스크를 사용하지 않게 할 수도 있습니다.
이렇게 하려면 아무 작업이나 마우스 오른쪽 버튼으로 클릭하고 작업 사용 안 함을 선택합니다:

왼쪽 메뉴를 사용하여 태스크를 탐색할 수도 있습니다.

GOAP 액션
마찬가지로, HFSM의 상태에서도 모든 작업에는 자신의 서브-그래프가 있습니다.
하지만 GOAP 서브-그래프는 새로운 GOAP를 만들 수 없습니다.
여기에는 계층 개념이 없습니다.
따라서 작업의 액션을 정의하는 데만 이 옵션을 사용합니다.
GOAP의 액션은 HFSM 액션과 매우 유사합니다.
태스크에서 수행할 액션 목록을 설정해야 합니다.
GOAP의 차이점은 On Update 액션 목록만 있다는 것입니다.
수행할 작업 목록을 정의할 서브-그래프로 이동할 작업을 두 번 클릭합니다.

GOAP 컴파일하기
생성한 GOAP를 실제로 사용하려면 수행한 작업을 컴파일해야 합니다.
컴파일하기 위해서는 2가지 옵션이 있습니다:

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

GOAP Coding
월드 상태 선언하기
GOAP를 사용할 때는 작업 조건 및 효과로 사용할 세계 상태를 정의해야 합니다.
이 프레임워크는 이미 미리 정의된 월드 상태 집합과 같이 제공되기 때문에 내 것으로 교체해야 합니다.
프로젝트에서 이것을 찾으려면 GOAP.qtn 파일을 검색해야 합니다.
"BotSDK/AI/GOAP" 폴더의 quantum.state 프로젝트에 위치해 있어야 합니다.
이 파일을 열 때 월드 상태에 대한 정의를 볼 수 있습니다.
이곳이 나의 플래그로 대신할 수 있는 곳입니다.
C#
enum GOAPWorldState : Int64 {
Root = 1, TargetSelected = 2, CarryingTarget = 4, TargetDelivered = 8
}
이 열거형을 변경하고 quantum.state 프로젝트를 컴파일할 때 이 값은 조건 및 효과 GOAP 편집기에서 사용할 수 있습니다.
Goap 에이전트 사용하기
엔티티내에서 GOAP 에이전트를 선언하는 방법은 다음과 같습니다:
C#
entity MyEntity[6] {
use Transform2D;
use DynamicBody;
use Prefab;
fields {
player_ref Player;
GOAPAgent GOAPAgent;
}
}
그러나 에이전트는 구조체이므로 엔티티 내에서만 사용할 수 있도록 제한되어 있지 않습니다.
GOAP 업데이터
이미 살펴본 바와 같이 GOAP Visual Editor에서 작업 집합을 정의했습니다.
이러한 작업은 GOAP 에이전트가 목표 상태를 달성하기 위해 사용하려고 하는 태스크입니다.
GOAP 에이전트 상태를 업데이트하려면 GOAPUpdater
를 사용해야 합니다.
하지만 실제로 업데이터를 사용하기 전에 사용할 수 있는 태스크가 무엇인지 알아야 합니다.
이 작업은 먼저 초기화 프로세스에서 수행됩니다.
원하는 대로 관리할 수 있지만, 예를 들어 간단한 사례를 분석해 보겠습니다.
가장 먼저 해야 할 일은 GOAPUpdater
를 인스턴스화하는 것입니다.
다음과 같은 방식으로 quantum 코드로 수행할 수 있습니다.
C#
private GOAPUpdater goapUpdater = new GOAPUpdater();
이제 에이전트의 GOAP 정보를 사용하여 초기화해야 합니다:
C#
goapUpdater.InitGOAPUpdater(runtimePlayerData.GOAPRoot);
컴파일 후 생성된 파일인 GOAPRoot
(컴파일 후 생성된 파일)에 액세스함으로써, 업데이터는 GOAP가 보유하고 있는 작업을 알고 있으므로 계획 및 액션에 사용할 준비가 되었습니다.
여기서 중요한 개념은 특정 작업 집합을 사용하도록 업데이터를 초기화하면 동일한 업데이터를 사용하여 다른 작업 집합을 가진 GOAP 에이전트를 업데이트할 수 없다는 것입니다.
따라서 다음 중 하나가 필요할 수 있습니다:
- 다른 GOAPRoot를 사용하여 GOAPUpdater를 다시 초기화합니다.
- 이러한 다른 유형의 에이전트에 대해 새로운 GOAPUpdater를 생성하고 특정 GOAPRoot로 업데이터를 초기화합니다.
GOAP 에이전트의 목표 설정하기
이제 초기화된 업데이터를 갖게 되었으니 GOAP 에이전트도 초기화해야 합니다.
이 작업은 두 가지 간단한 단계로 수행됩니다:
GOAPWorldState
를 이용해 새로운 목표를 수립합니다.목표는 양수 값과 음수 값을 모두 지원합니다.
C#
GOAPState goal = new GOAPState(); goal.Positive = (Int64)GOAPWorldState.TargetDelivered; goal.Negative = (Int64)GOAPWorldState.CarryingTarget;
에이전트의 목표로 설정합니다.
C#
myEntity->Fields.GOAPAgent.SetGoal(goal);
GOAP 에이전트 업데이트하기
이제 다음을 갖게 되었습니다:
- 초기화된
GOAPUpdater
- 초기화된
GOAPAgent
마침내 우리는 Bot를 운전하는 데 두 개를 모두 사용하는 것으로 옮겨갈 수 있습니다.
게임 로직에 따라 에이전트의 현재 상태를 업데이트해야 합니다.
이를 위해서는, 필요할 때마다 다음과 같이 업데이트할 수 있습니다:
C#
myEntity->Fields.GOAPAgent.CurrentState = (Int64)state;
또한 업데이터를 사용하여 에이전트를 업데이트해야 새 계획을 세우고 현재 상태와 목표에 따라 작업 집합을 실행할 수 있습니다:
C#
goapUpdater.UpdateGOAPAgent(f, &myEntity->Fields.GOAPAgent, (Entity*)myEntity);
GOAP 액션
일반적으로 액션은 두 AI 모델에 공통적인 개념이기 때문에 GOAP 작업을 생성하는 워크플로우도 HFSM 작업을 생성하는 것과 동일합니다.
따라서 한 모델에 대한 작업을 생성할 때마다 다른 모델에서도 직접 사용할 수 있습니다.
새로운 액션을 생성하기 위해, quantum_code 솔루션을 열어야 합니다.
quantum.state 프로젝트에서는 AIAction
추상 클래스에서 상속되는 클래스를 만들 수 있습니다.
이렇게 할 때는 Update
메소드를 구현해야 합니다.
그러면 HFSM이 업데이트될 때마다 실행될 코드가 저장됩니다.
새 클래스를 [Serializable]
으로 표시해야 합니다.
C#
namespace Quantum
{
[Serializable]
public class IdleAction : AIAction
{
public override unsafe void Update (Frame f, Entity* e)
{
// insert the action code here
}
}
}
Back to top