[C++/UE] UE5中AI開發的一點功能梳理(一) – 行為樹創建

        首先,這裡先放幾條在研究過程中得到特別大幫助的一些參考資料鏈接:

行為樹 Behavior Tree

事前準備

  • 創建繼承了AI Controller父類的藍圖
  • 創建AI角色(Character)
    • 在Character -> Pawn設置中進行AI Controller Class和 Auto Possess AI的配置
  • 參數說明
    • AI Controller Class -> 這個角色對應的繼承了AI Controller父類的藍圖
    • Auto Possess AI -> 指的是AI Controller Class要怎樣接管Character(AI Controller接管了Character才能使AI生效)
      • Placed in World:一開始就放在場景的Character會被自動接管
        • 如果Character後面被卸載了,再重新生成出來,就不會再被AI Controller Class接管
      • Spawned:場景加載完之後,再被生成出來的Character會被自動接管,也就是說一開始就放置在場景裡的Character不會被AI Controller Class接管
      • Placed in World or Spawned:只要Character被創建出來就自動接管
      • Disable -> 不自動接管,需要在AI Controller裡手動接管
        • AI Controller裡使用Possess節點(Server Only),接受一個接管對象參數
//Pawn.cpp

void APawn::PostInitializeComponents()
{
    QUICK_SCOPE_CYCLE_COUNTER(STAT_Pawn_PostInitComponents);

    Super::PostInitializeComponents();
    
    if (IsValid(this))
    {
        UWorld* World = GetWorld();

        // Automatically add Controller to AI Pawns if we are allowed to.
        if (AutoPossessPlayer == EAutoReceiveInput::Disabled
            && AutoPossessAI != EAutoPossessAI::Disabled && Controller == nullptr && GetNetMode() != NM_Client
#if WITH_EDITOR
            && (GIsEditor == false || World->IsGameWorld())
#endif // WITH_EDITOR
            )
        {
            const bool bPlacedInWorld = (World->bStartup);
            if ((AutoPossessAI == EAutoPossessAI::PlacedInWorldOrSpawned) ||
                (AutoPossessAI == EAutoPossessAI::PlacedInWorld && bPlacedInWorld) ||
                (AutoPossessAI == EAutoPossessAI::Spawned && !bPlacedInWorld))
            {
                SpawnDefaultController();
            }
        }

        // update movement component's nav agent values
        UpdateNavAgent();
    }
}

void APawn::SpawnDefaultController()
{
    if ( Controller != nullptr || GetNetMode() == NM_Client)
    {
        return;
    }

    if (AIControllerClass != nullptr)
    {
        FActorSpawnParameters SpawnInfo;
        SpawnInfo.Instigator = GetInstigator();
        SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
        SpawnInfo.OverrideLevel = GetLevel();
        SpawnInfo.ObjectFlags |= RF_Transient;    // We never want to save AI controllers into a map
        AController* NewController = GetWorld()->SpawnActor<AController>(AIControllerClass, GetActorLocation(), GetActorRotation(), SpawnInfo);
        if (NewController != nullptr)
        {
            // if successful will result in setting this->Controller 
            // as part of possession mechanics
            NewController->Possess(this);
        }
    }
}

使用說明

  • 創建Blackboard資源
    • 用於管理行為樹(s)可用的變量Key,使行為樹可以追蹤、控制AI Agent的狀態
  • 創建行為樹
    • 在樹界面有一個根節點,也是行為樹運行的起點
    • Detail界面要求指定一個Blackboard資源
      • 使這個行為樹能基於該Blackboard的Key狀態執行不同的行為