Snippets
這裡提供了一些可與 Bot SDK 一起使用的實用程式碼片段。
複合型代理
有時候,在同一個實體中使用多個 AI 代理元件可能會很有用。
例如,可能有一個 HFSM 專門負責實體的移動,而另一個 HFSM 則僅負責攻擊目標。
甚至可以在同一個實體中混合使用不同的技術:也許部分工作由 HFSM 完成,另一部分則由 BT 完成。
當需要這樣的設置時,為實體提供多個記憶體儲存空間也會很有用。在 Bot SDK 中,通常(但不是強制性的)會使用 AIBlackboard 元件。
以下是一些程式碼片段,展示了如何將多個元件新增到單個實體中,以創建我們在此稱為「複合型代理」的實體:
創建複合元件
在 DSL(任何.qtn
檔案)中,新增以下元件。
可以根據遊戲需求為元件命名,或將其以通用方式新增到列表中。
在這個範例中,有一個 HFSM 僅負責移動實體,另一個則負責攻擊(僅供說明):
Qtn
component CompoundAgents
{
HFSMAgent MovementHFSMAgent;
HFSMAgent AttackHFSMAgent;
AIBlackboardComponent MovementBlackboard;
AIBlackboardComponent AttackBlackboard;
AssetRefAIBlackboardInitializer MovementBBInitializer;
AssetRefAIBlackboardInitializer AttackBBInitializer;
}
擴展 AIContext
創建一個AIContextUser
的部分實現。這裡的上下文僅為範例:「根據更新的實體,正在更新的是哪個 HFSM?該 HFSM 使用哪個 Blackboard?」等等:
C#
namespace Quantum
{
public unsafe partial struct AIContextUser
{
public readonly AIBlackboardComponent* Blackboard;
public readonly HFSMAgent* HFSMAgent;
public AIContextUser(AIBlackboardComponent* blackboard, HFSMAgent* hfsmAgent)
{
Blackboard = blackboard;
HFSMAgent = hfsmAgent;
}
}
}
初始化代理與 Blackboard
這裡以 ISignalOnComponentAdded
C#
public void OnAdded(Frame frame, EntityRef entity, CompoundAgents* compoundAgents)
{
// Initialise Agents
HFSMRoot hfsmRoot = frame.FindAsset<HFSMRoot>(compoundAgents->MovementHFSMAgent.Data.Root.Id);
HFSMManager.Init(frame, &compoundAgents->MovementHFSMAgent.Data, entity, hfsmRoot);
hfsmRoot = frame.FindAsset<HFSMRoot>(compoundAgents->AttackHFSMAgent.Data.Root.Id);
HFSMManager.Init(frame, &compoundAgents->AttackHFSMAgent.Data, entity, hfsmRoot);
// Initialise Blackboards
AIBlackboardInitializer initializer = frame.FindAsset<AIBlackboardInitializer>(compoundAgents->MovementBBInitializer.Id);
AIBlackboardInitializer.InitializeBlackboard(frame, &compoundAgents->MovementBlackboard, initializer);
initializer = frame.FindAsset<AIBlackboardInitializer>(compoundAgents->AttackBBInitializer.Id);
AIBlackboardInitializer.InitializeBlackboard(frame, &compoundAgents->AttackBlackboard, initializer);
}
更新所有代理
創建 AI 上下文並填充每個 HFSM 和 Blackboard,然後執行更新:
C#
public override void Update(Frame frame, ref Filter filter)
{
HFSMData* movementData = &filter.CompoundAgents->MovementHFSMAgent.Data;
HFSMData* rotationData = &filter.CompoundAgents->RotationHFSMAgent.Data;
HFSMData* attackData = &filter.CompoundAgents->AttackHFSMAgent.Data;
AIContext aiContext = new AIContext();
AIContextUser movementContext = new AIContextUser(&filter.CompoundAgents->MovementHFSMAgent, &filter.CompoundAgents->MovementBlackboard);
aiContext.UserData = &userData;
HFSMManager.Update(frame, frame.DeltaTime, movementData, filter.EntityRef, ref aiContext);
AIContextUser rotationContext = new AIContextUser(&filter.CompoundAgents->RotationHFSMAgent, &filter.CompoundAgents->RotationBlackboard);
aiContext.UserData = &userData;
HFSMManager.Update(frame, frame.DeltaTime, rotationData, filter.EntityRef, ref aiContext);
AIContextUser attackContext = new AIContextUser(&filter.CompoundAgents->AttackHFSMAgent, &filter.CompoundAgents->AttackBlackboard);
aiContext.UserData = &userData;
HFSMManager.Update(frame, frame.DeltaTime, attackData, filter.EntityRef, ref aiContext);
}
從 AIContext 物件中獲取 HFSM 專用的 Blackboard
以下是一個動作的程式碼片段,該動作會寫入上下文專用的 Blackboard。請注意,它是與具體 Blackboard 無關的,因此程式碼是解耦的,無需在動作中新增大量樣板程式碼來確定應該使用哪個 Blackboard。
這裡有一個 擴展方法,可以轉換為用戶上下文類型:
C#
namespace Quantum
{
[System.Serializable]
public unsafe class WriteBlackboardCompound : AIAction
{
public int Value;
public override void Update(Frame frame, EntityRef entity, ref AIContext aiContext)
{
aiContext.UserData().Blackboard->Set(frame, "TestInteger", Value);
}
}
}
Back to top