├── .gitattributes ├── Source └── UtilityAI │ ├── Private │ ├── AgentData.cpp │ ├── Operations │ │ ├── Operation.cpp │ │ ├── Not.cpp │ │ ├── Or.cpp │ │ ├── Xor.cpp │ │ ├── And.cpp │ │ ├── Select.cpp │ │ ├── UnaryOperation.cpp │ │ ├── InRange.cpp │ │ ├── BinaryOperation.cpp │ │ ├── TernaryOperation.cpp │ │ └── MultiOperation.cpp │ ├── Debugging │ │ ├── DebuggerSettings.cpp │ │ └── UtilityAIDebuggerComponent.cpp │ ├── Agent.cpp │ ├── Actions │ │ ├── BehaviorTreeAction.cpp │ │ ├── BrainAction.cpp │ │ └── Action.cpp │ ├── Statics │ │ ├── UtilityAIConstants.cpp │ │ └── UtilityAIStatics.cpp │ ├── Predicates │ │ ├── Predicate.cpp │ │ └── ComplexPredicate.cpp │ ├── Expression.cpp │ ├── Components │ │ ├── TimedBrainComponent.cpp │ │ └── UtilityAIBrainComponent.cpp │ ├── Condition.cpp │ ├── UtilityAI.cpp │ └── Brains │ │ └── BrainAsset.cpp │ ├── Public │ ├── Operations │ │ ├── Operation.h │ │ ├── Or.h │ │ ├── And.h │ │ ├── Not.h │ │ ├── Xor.h │ │ ├── InRange.h │ │ ├── Select.h │ │ ├── UnaryOperation.h │ │ ├── BinaryOperation.h │ │ ├── TernaryOperation.h │ │ └── MultiOperation.h │ ├── AgentData.h │ ├── Debugging │ │ ├── DebuggerSettings.h │ │ └── UtilityAIDebuggerComponent.h │ ├── Actions │ │ ├── BrainAction.h │ │ ├── BehaviorTreeAction.h │ │ └── Action.h │ ├── Predicates │ │ ├── ComplexPredicate.h │ │ └── Predicate.h │ ├── UtilityAI.h │ ├── Agent.h │ ├── Statics │ │ ├── UtilityAIConstants.h │ │ └── UtilityAIStatics.h │ ├── Expression.h │ ├── Condition.h │ ├── Components │ │ ├── TimedBrainComponent.h │ │ └── UtilityAIBrainComponent.h │ └── Brains │ │ └── BrainAsset.h │ └── UtilityAI.Build.cs ├── Resources └── Icon128.png ├── .gitignore ├── UtilityAI.uplugin └── Readme.md /.gitattributes: -------------------------------------------------------------------------------- 1 | Content/** filter=lfs diff=lfs merge=lfs -text 2 | Resources/** filter=lfs diff=lfs 3 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/AgentData.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "AgentData.h" 4 | -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:93f0f34ab64d1d3b0befa18c569193b4ea9092cdf85d795cb634fdcf399f5169 3 | size 3227 4 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/Operation.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Operation.h" 4 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Debugging/DebuggerSettings.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "DebuggerSettings.h" 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Binaries 2 | DerivedDataCache 3 | Intermediate 4 | Saved 5 | .vscode 6 | .vs 7 | *.VC.db 8 | *.opensdf 9 | *.opendb 10 | *.sdf 11 | *.sln 12 | *.suo 13 | *.xcodeproj 14 | *.xcworkspace -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Agent.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Agent.h" 4 | 5 | // Add default functionality here for any IAgent functions that are not pure virtual. 6 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/Not.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Not.h" 4 | 5 | bool UNot::ExpressionValue_Implementation(const TScriptInterface& Agent) 6 | { 7 | return !FirstResult(Agent); 8 | } 9 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/Or.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Or.h" 4 | 5 | bool UOr::ExpressionValue_Implementation(const TScriptInterface& Agent) 6 | { 7 | return FirstResult(Agent) || SecondResult(Agent); 8 | } 9 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/Xor.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Xor.h" 4 | 5 | bool UXor::ExpressionValue_Implementation(const TScriptInterface& Agent) 6 | { 7 | return FirstResult(Agent) ^ SecondResult(Agent); 8 | } 9 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/And.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "And.h" 4 | 5 | bool UAnd::ExpressionValue_Implementation(const TScriptInterface& Agent) 6 | { 7 | return FirstResult(Agent) && SecondResult(Agent); 8 | } 9 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/Select.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Select.h" 4 | 5 | bool USelect::ExpressionValue_Implementation(const TScriptInterface& Agent) 6 | { 7 | return FirstResult(Agent) ? SecondResult(Agent) : ThirdResult(Agent); 8 | } 9 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Actions/BehaviorTreeAction.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "BehaviorTreeAction.h" 4 | #include "Agent.h" 5 | 6 | void UBehaviorTreeAction::Run_Implementation(const TScriptInterface& Agent) const 7 | { 8 | Agent->RunBehavior(Behavior); 9 | } 10 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/Operation.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "Expression.h" 6 | #include "Operation.generated.h" 7 | 8 | /** 9 | * 10 | */ 11 | UCLASS(BlueprintType, Abstract) 12 | class UTILITYAI_API UOperation : public UExpression 13 | { 14 | GENERATED_BODY() 15 | }; 16 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/AgentData.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "UObject/NoExportTypes.h" 7 | #include "AgentData.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS(BlueprintType, Blueprintable) 13 | class UTILITYAI_API UAgentData : public UObject 14 | { 15 | GENERATED_BODY() 16 | }; 17 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/Or.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operations/BinaryOperation.h" 7 | #include "Or.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UTILITYAI_API UOr : public UBinaryOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | protected: 18 | bool ExpressionValue_Implementation(const TScriptInterface& Agent) override; 19 | }; 20 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/And.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operations/BinaryOperation.h" 7 | #include "And.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UTILITYAI_API UAnd : public UBinaryOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | protected: 18 | bool ExpressionValue_Implementation(const TScriptInterface& Agent) override; 19 | }; 20 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/Not.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operations/UnaryOperation.h" 7 | #include "Not.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UTILITYAI_API UNot : public UUnaryOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | protected: 18 | bool ExpressionValue_Implementation(const TScriptInterface& Agent) override; 19 | }; 20 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/Xor.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operations/BinaryOperation.h" 7 | #include "Xor.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UTILITYAI_API UXor : public UBinaryOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | protected: 18 | bool ExpressionValue_Implementation(const TScriptInterface& Agent) override; 19 | }; 20 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/InRange.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operations/MultiOperation.h" 7 | #include "InRange.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UTILITYAI_API UInRange : public UMultiOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | protected: 18 | bool ExpressionValue_Implementation(const TScriptInterface& Agent) override; 19 | }; 20 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/Select.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operations/TernaryOperation.h" 7 | #include "Select.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UTILITYAI_API USelect : public UTernaryOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | protected: 18 | bool ExpressionValue_Implementation(const TScriptInterface& Agent) override; 19 | }; 20 | -------------------------------------------------------------------------------- /UtilityAI.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "0.1", 5 | "FriendlyName": "UtilityAI", 6 | "Description": "", 7 | "Category": "AI", 8 | "CreatedBy": "Ivan Korotkov", 9 | "CreatedByURL": "", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "SupportURL": "", 13 | "CanContainContent": false, 14 | "IsBetaVersion": true, 15 | "Installed": false, 16 | "Modules": [ 17 | { 18 | "Name": "UtilityAI", 19 | "Type": "Runtime", 20 | "LoadingPhase": "Default" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Statics/UtilityAIConstants.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "UtilityAIConstants.h" 4 | 5 | float UUtilityAIConstants::MinActionRating() 6 | { 7 | return 0.0f; 8 | } 9 | 10 | float UUtilityAIConstants::MaxActionRating() 11 | { 12 | return 1.0f; 13 | } 14 | 15 | float UUtilityAIConstants::AbsoluteMin() 16 | { 17 | return MinActionRating() - 1.f; 18 | } 19 | 20 | float UUtilityAIConstants::AbsoluteMax() 21 | { 22 | return MaxActionRating() + 1.f; 23 | } 24 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Debugging/DebuggerSettings.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "UObject/NoExportTypes.h" 7 | #include "DebuggerSettings.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | USTRUCT(BlueprintType) 13 | struct UTILITYAI_API FDebuggerSettings 14 | { 15 | GENERATED_BODY() 16 | 17 | UPROPERTY(EditAnywhere) 18 | bool bStripPredicateNames = true; 19 | 20 | UPROPERTY(EditAnywhere) 21 | bool bStripActionNames = true; 22 | }; 23 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Actions/BrainAction.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Actions/Action.h" 7 | #include "BrainAction.generated.h" 8 | 9 | class UBrainAsset; 10 | /** 11 | * 12 | */ 13 | UCLASS() 14 | class UTILITYAI_API UBrainAction : public UAction 15 | { 16 | GENERATED_BODY() 17 | 18 | public: 19 | void Run_Implementation(const TScriptInterface& Agent) const override; 20 | 21 | private: 22 | UPROPERTY(EditAnywhere) 23 | UBrainAsset* Brain; 24 | }; 25 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Actions/BrainAction.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "BrainAction.h" 4 | #include "UtilityAI.h" 5 | #include "BrainAsset.h" 6 | 7 | void UBrainAction::Run_Implementation(const TScriptInterface& Agent) const 8 | { 9 | Super::Run(Agent); 10 | if (Brain == nullptr) 11 | { 12 | UE_LOG(UtilityAI_Actions, Warning, TEXT("Action %s has no associated brain asset"), *GetName()); 13 | return; 14 | } 15 | if (const auto Action = Brain->SelectAction(Agent)) 16 | { 17 | Action->Run(Agent); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Actions/BehaviorTreeAction.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "Action.h" 6 | #include "BehaviorTreeAction.generated.h" 7 | 8 | class UBehaviorTree; 9 | /** 10 | * 11 | */ 12 | UCLASS(BlueprintType, Blueprintable, Abstract) 13 | class UTILITYAI_API UBehaviorTreeAction : public UAction 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | void Run_Implementation(const TScriptInterface& Agent) const override; 19 | 20 | private: 21 | UPROPERTY(EditAnywhere) 22 | UBehaviorTree* Behavior; 23 | }; 24 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/UnaryOperation.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "UnaryOperation.h" 4 | 5 | void UUnaryOperation::GetPredicatesRecursively(FPredicatesContainerRef Predicates) 6 | { 7 | return Operand->GetPredicatesRecursively(Predicates); 8 | } 9 | 10 | UExpression* UUnaryOperation::First() const 11 | { 12 | return Operand; 13 | } 14 | 15 | bool UUnaryOperation::FirstResult(const TScriptInterface& Agent) const 16 | { 17 | return First()->Evaluate(Agent); 18 | } 19 | 20 | void UUnaryOperation::Init(UExpression* F) 21 | { 22 | Operand = F; 23 | } 24 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Predicates/Predicate.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Predicate.h" 4 | #include "UtilityAI.h" 5 | 6 | bool UPredicate::ExpressionValue_Implementation(const TScriptInterface& Agent) 7 | { 8 | return false; 9 | } 10 | 11 | bool UPredicate::Evaluate(const TScriptInterface& Agent) 12 | { 13 | const auto Value = Super::Evaluate(Agent); 14 | OnEvaluated.Broadcast(GetName(), Value); 15 | return Value; 16 | } 17 | 18 | void UPredicate::GetPredicatesRecursively(FPredicatesContainerRef Predicates) 19 | { 20 | Predicates.Add(this); 21 | } 22 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Predicates/ComplexPredicate.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Predicate.h" 7 | #include "ComplexPredicate.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UTILITYAI_API UComplexPredicate : public UPredicate 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | bool ExpressionValue_Implementation(const TScriptInterface& Agent) override; 19 | 20 | protected: 21 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent) 22 | UExpression* AssignExpression(const TScriptInterface& Agent) const; 23 | 24 | private: 25 | UPROPERTY() 26 | UExpression* Expression; 27 | }; 28 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Expression.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Expression.h" 4 | #include "UtilityAI.h" 5 | 6 | bool UExpression::ExpressionValue_Implementation(const TScriptInterface& Agent) 7 | { 8 | UE_LOG(UtilityAI, Error, TEXT("Expression %s has no overriden evaluate behavior"), *GetName()); 9 | return false; 10 | } 11 | 12 | bool UExpression::Evaluate(const TScriptInterface& Agent) 13 | { 14 | return ExpressionValue(Agent); 15 | } 16 | 17 | void UExpression::GetPredicatesRecursively(FPredicatesContainerRef Predicates) 18 | { 19 | UE_LOG(UtilityAI, Error, TEXT("Expression %s does not provide any way to access underlying predicates"), *GetName()); 20 | } 21 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Predicates/ComplexPredicate.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "ComplexPredicate.h" 4 | #include "UtilityAI.h" 5 | 6 | bool UComplexPredicate::ExpressionValue_Implementation(const TScriptInterface& Agent) 7 | { 8 | Super::Evaluate(Agent); 9 | if (Expression == nullptr) 10 | { 11 | Expression = AssignExpression(Agent); 12 | } 13 | return Expression && Expression->Evaluate(Agent); 14 | } 15 | 16 | UExpression* UComplexPredicate::AssignExpression_Implementation(const TScriptInterface& Agent) const 17 | { 18 | UE_LOG(UtilityAI_Predicates, Error, TEXT("There is no expression defined for predicate %s"), *GetName()); 19 | return nullptr; 20 | } 21 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/InRange.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "InRange.h" 4 | #include "UtilityAI.h" 5 | 6 | bool UInRange::ExpressionValue_Implementation(const TScriptInterface& Agent) 7 | { 8 | if (ArgsNum() < 2) 9 | { 10 | UE_LOG(UtilityAI_Operations, Error, TEXT("Operation %s hasn't enought arguments passed. Passes: %d, required: %d"), *GetName(), ArgsNum(), 2); 11 | return false; 12 | } 13 | const auto Lower = NthArg(0); 14 | const auto Upper = NthArg(1); 15 | const auto Results = OperandsResults(Agent); 16 | auto Count = 0; 17 | for (const auto Value : Results) 18 | { 19 | if (Value) 20 | { 21 | ++Count; 22 | } 23 | } 24 | return Lower <= Count && Count < Upper; 25 | } 26 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/UtilityAI.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "Modules/ModuleManager.h" 6 | 7 | class FUtilityAIModule : public IModuleInterface 8 | { 9 | public: 10 | /** IModuleInterface implementation */ 11 | void StartupModule() override; 12 | void ShutdownModule() override; 13 | }; 14 | 15 | DECLARE_LOG_CATEGORY_EXTERN(UtilityAI_Actions, Log, All) 16 | DECLARE_LOG_CATEGORY_EXTERN(UtilityAI_Brains, Log, All) 17 | DECLARE_LOG_CATEGORY_EXTERN(UtilityAI_Predicates, Log, All) 18 | DECLARE_LOG_CATEGORY_EXTERN(UtilityAI_Operations, Log, All) 19 | DECLARE_LOG_CATEGORY_EXTERN(UtilityAI_Components, Log, All) 20 | DECLARE_LOG_CATEGORY_EXTERN(UtilityAI_Statics, Log, All) 21 | DECLARE_LOG_CATEGORY_EXTERN(UtilityAI_Debugging, Log, All) 22 | DECLARE_LOG_CATEGORY_EXTERN(UtilityAI, Log, All) 23 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Predicates/Predicate.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Expression.h" 7 | #include "Predicate.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS(BlueprintType, Abstract, Blueprintable) 13 | class UTILITYAI_API UPredicate : public UExpression 14 | { 15 | GENERATED_BODY() 16 | 17 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FPredicateSignature, FString, PredicateName, bool, Success); 18 | 19 | public: 20 | FPredicateSignature OnEvaluated; 21 | 22 | bool Evaluate(const TScriptInterface& Agent) override; 23 | 24 | void GetPredicatesRecursively(FPredicatesContainerRef Predicates) override; 25 | 26 | protected: 27 | bool ExpressionValue_Implementation(const TScriptInterface& Agent) override; 28 | }; 29 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Agent.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "UObject/Interface.h" 7 | #include "Agent.generated.h" 8 | 9 | class UAgentData; 10 | class UBehaviorTree; 11 | // This class does not need to be modified. 12 | UINTERFACE(MinimalAPI) 13 | class UAgent : public UInterface 14 | { 15 | GENERATED_BODY() 16 | }; 17 | 18 | /** 19 | * 20 | */ 21 | class UTILITYAI_API IAgent 22 | { 23 | GENERATED_BODY() 24 | 25 | // Add interface functions to this class. This is the class that will be inherited to implement this interface. 26 | public: 27 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent) 28 | void RunBehavior(const UBehaviorTree* Behavior); 29 | 30 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent) 31 | UAgentData* GetAgentData(); 32 | }; 33 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/UnaryOperation.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operation.h" 7 | #include "UnaryOperation.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS(BlueprintType, Abstract, Blueprintable) 13 | class UTILITYAI_API UUnaryOperation : public UOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | friend class UUtilityAIStatics; 18 | 19 | public: 20 | void GetPredicatesRecursively(FPredicatesContainerRef Predicates) override; 21 | 22 | protected: 23 | UFUNCTION(BlueprintCallable) 24 | UExpression* First() const; 25 | 26 | UFUNCTION(BlueprintCallable) 27 | bool FirstResult(const TScriptInterface& Agent) const; 28 | 29 | private: 30 | UPROPERTY() 31 | UExpression* Operand; 32 | 33 | void Init(UExpression* F); 34 | }; 35 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Components/TimedBrainComponent.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "TimedBrainComponent.h" 4 | #include "Engine/World.h" 5 | #include "TimerManager.h" 6 | 7 | void UTimedBrainComponent::Start() 8 | { 9 | if (!Handle.IsValid()) 10 | { 11 | GetWorld()->GetTimerManager().SetTimer(Handle, this, &UTimedBrainComponent::Act, Rate, true, FirstDelay); 12 | } 13 | } 14 | 15 | void UTimedBrainComponent::Stop() 16 | { 17 | if (Handle.IsValid()) 18 | { 19 | GetWorld()->GetTimerManager().ClearTimer(Handle); 20 | } 21 | } 22 | 23 | void UTimedBrainComponent::BeginPlay() 24 | { 25 | Super::BeginPlay(); 26 | Start(); 27 | } 28 | 29 | void UTimedBrainComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) 30 | { 31 | Super::EndPlay(EndPlayReason); 32 | Stop(); 33 | } 34 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Statics/UtilityAIConstants.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Kismet/BlueprintFunctionLibrary.h" 7 | #include "UtilityAIConstants.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UTILITYAI_API UUtilityAIConstants : public UBlueprintFunctionLibrary 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | UFUNCTION(Category = "Utility AI|Constants", BlueprintPure) 19 | static float MinActionRating(); 20 | 21 | UFUNCTION(Category = "Utility AI|Constants", BlueprintPure) 22 | static float MaxActionRating(); 23 | 24 | UFUNCTION(Category = "Utility AI|Constants", BlueprintPure) 25 | static float AbsoluteMin(); 26 | 27 | UFUNCTION(Category = "Utility AI|Constants", BlueprintPure) 28 | static float AbsoluteMax(); 29 | }; 30 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Condition.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Condition.h" 4 | #include "Agent.h" 5 | #include "Predicate.h" 6 | #include "SubclassOf.h" 7 | 8 | void FCondition::EnsurePredicateIsCreated(const TScriptInterface& Agent) const 9 | { 10 | if (Predicate == nullptr) 11 | { 12 | Predicate = NewObject(Agent.GetObject(), PredicateClass); 13 | } 14 | } 15 | 16 | float FCondition::Evaluate(const TScriptInterface& Agent) 17 | { 18 | EnsurePredicateIsCreated(Agent); 19 | return Predicate && Predicate->Evaluate(Agent) ? SuccessValue : FailureValue; 20 | } 21 | 22 | FString FCondition::GetName() const 23 | { 24 | return Name; 25 | } 26 | 27 | UPredicate* FCondition::GetPredicate(const TScriptInterface& Agent) const 28 | { 29 | EnsurePredicateIsCreated(Agent); 30 | return Predicate; 31 | } 32 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | ## Cleanup 4 | 5 | ## Fixes and enhancements 6 | 7 | - [ ] multioperations can get invalid number of arguments - fix 8 | - [ ] array of conditions keeps collapsing when adding new conditions 9 | 10 | ## Improvements 11 | 12 | ## Deprecation 13 | 14 | - [ ] TicTacToe example 15 | - finish or 16 | - delete 17 | 18 | ## Features 19 | 20 | - [ ] add description to actions/predicates 21 | - [ ] add multiple passes to Utility Ai component (each pass is a single brain asset) 22 | - [x] add action that can execute another brain 23 | - *needs testing* 24 | - [ ] add action stack to debug actions that execute brain 25 | - [ ] add action log to see which action where executed in the past 26 | 27 | ## Performance 28 | 29 | ## Propositions 30 | 31 | ## Docs 32 | 33 | I need to write an actual doc! 34 | 35 | ## Contribution 36 | 37 | Create a dedicated file and move this section there! 38 | -------------------------------------------------------------------------------- /Source/UtilityAI/UtilityAI.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class UtilityAI : ModuleRules 6 | { 7 | public UtilityAI(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange( 12 | new string[] 13 | { 14 | "Core", 15 | "AIModule", 16 | } 17 | ); 18 | 19 | 20 | PrivateDependencyModuleNames.AddRange( 21 | new string[] 22 | { 23 | "CoreUObject", 24 | "Engine", 25 | "Slate", 26 | "SlateCore", 27 | // ... add private dependencies that you statically link with here ... 28 | } 29 | ); 30 | 31 | 32 | DynamicallyLoadedModuleNames.AddRange( 33 | new string[] 34 | { 35 | // ... add any modules that your module loads dynamically here ... 36 | } 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/BinaryOperation.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "BinaryOperation.h" 4 | 5 | void UBinaryOperation::GetPredicatesRecursively(FPredicatesContainerRef Predicates) 6 | { 7 | Operand1->GetPredicatesRecursively(Predicates); 8 | Operand2->GetPredicatesRecursively(Predicates); 9 | } 10 | 11 | UExpression* UBinaryOperation::First() const 12 | { 13 | return Operand1; 14 | } 15 | 16 | UExpression* UBinaryOperation::Second() const 17 | { 18 | return Operand2; 19 | } 20 | 21 | bool UBinaryOperation::FirstResult(const TScriptInterface& Agent) const 22 | { 23 | return First()->Evaluate(Agent); 24 | } 25 | 26 | bool UBinaryOperation::SecondResult(const TScriptInterface& Agent) const 27 | { 28 | return Second()->Evaluate(Agent); 29 | } 30 | 31 | void UBinaryOperation::Init(UExpression* F, UExpression* S) 32 | { 33 | Operand1 = F; 34 | Operand2 = S; 35 | } 36 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Components/UtilityAIBrainComponent.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "UtilityAIBrainComponent.h" 4 | #include "BrainAsset.h" 5 | #include "Action.h" 6 | 7 | UUtilityAIBrainComponent::UUtilityAIBrainComponent() 8 | { 9 | PrimaryComponentTick.bCanEverTick = true; 10 | } 11 | 12 | void UUtilityAIBrainComponent::Act_Implementation() const 13 | { 14 | OnBeforeAct.Broadcast(); 15 | const TScriptInterface Agent = GetOwner(); 16 | if (const auto Action = Asset->SelectAction(Agent)) 17 | { 18 | OnActionRun.Broadcast(Action->GetName()); 19 | Action->Run(Agent); 20 | } 21 | OnAfterAct.Broadcast(); 22 | } 23 | 24 | UBrainAsset* UUtilityAIBrainComponent::GetBrainAsset() const 25 | { 26 | return Asset; 27 | } 28 | 29 | void UUtilityAIBrainComponent::BeginPlay() 30 | { 31 | Super::BeginPlay(); 32 | Asset = NewObject(this, BrainAssetClass, TEXT("Brain Asset")); 33 | } 34 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Expression.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "UObject/NoExportTypes.h" 7 | #include "Expression.generated.h" 8 | 9 | class UPredicate; 10 | class IAgent; 11 | /** 12 | * 13 | */ 14 | UCLASS(BlueprintType, Abstract) 15 | class UTILITYAI_API UExpression : public UObject 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | using FPredicatesContainer = TSet; 21 | using FPredicatesContainerRef = FPredicatesContainer&; 22 | 23 | UFUNCTION(BlueprintCallable) 24 | virtual bool Evaluate(const TScriptInterface& Agent); 25 | 26 | virtual void GetPredicatesRecursively(FPredicatesContainerRef Predicates); 27 | 28 | protected: 29 | UFUNCTION(BlueprintNativeEvent) 30 | bool ExpressionValue(const TScriptInterface& Agent); 31 | virtual bool ExpressionValue_Implementation(const TScriptInterface& Agent); 32 | }; 33 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Condition.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "SubclassOf.h" 7 | #include "Condition.generated.h" 8 | 9 | class UPredicate; 10 | class IAgent; 11 | /** 12 | * 13 | */ 14 | USTRUCT(BlueprintType) 15 | struct UTILITYAI_API FCondition 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | float Evaluate(const TScriptInterface& Agent); 21 | 22 | FString GetName() const; 23 | 24 | UPredicate* GetPredicate(const TScriptInterface& Agent) const; 25 | 26 | private: 27 | UPROPERTY() 28 | mutable UPredicate* Predicate = nullptr; 29 | 30 | UPROPERTY(EditAnywhere) 31 | FString Name; 32 | 33 | UPROPERTY(EditAnywhere) 34 | TSubclassOf PredicateClass; 35 | 36 | UPROPERTY(EditAnywhere) 37 | float SuccessValue = 0.1f; 38 | 39 | UPROPERTY(EditAnywhere) 40 | float FailureValue = 0.0f; 41 | 42 | void EnsurePredicateIsCreated(const TScriptInterface& Agent) const; 43 | }; 44 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/UtilityAI.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "UtilityAI.h" 4 | 5 | #define LOCTEXT_NAMESPACE "FUtilityAIModule" 6 | 7 | void FUtilityAIModule::StartupModule() 8 | { 9 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 10 | } 11 | 12 | void FUtilityAIModule::ShutdownModule() 13 | { 14 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 15 | // we call this function before unloading the module. 16 | } 17 | 18 | #undef LOCTEXT_NAMESPACE 19 | 20 | IMPLEMENT_MODULE(FUtilityAIModule, UtilityAI) 21 | 22 | DEFINE_LOG_CATEGORY(UtilityAI_Actions) 23 | DEFINE_LOG_CATEGORY(UtilityAI_Brains) 24 | DEFINE_LOG_CATEGORY(UtilityAI_Predicates) 25 | DEFINE_LOG_CATEGORY(UtilityAI_Operations) 26 | DEFINE_LOG_CATEGORY(UtilityAI_Components) 27 | DEFINE_LOG_CATEGORY(UtilityAI_Statics) 28 | DEFINE_LOG_CATEGORY(UtilityAI_Debugging) 29 | DEFINE_LOG_CATEGORY(UtilityAI) 30 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Components/TimedBrainComponent.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "UtilityAIBrainComponent.h" 6 | #include "TimedBrainComponent.generated.h" 7 | 8 | /** 9 | * 10 | */ 11 | UCLASS(ClassGroup = (UtilityAI), meta = (BlueprintSpawnableComponent, DisplayName = "Timed Brain"), Blueprintable) 12 | class UTILITYAI_API UTimedBrainComponent : public UUtilityAIBrainComponent 13 | { 14 | GENERATED_BODY() 15 | 16 | DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBrainDelegate); 17 | 18 | public: 19 | FBrainDelegate OnStart; 20 | FBrainDelegate OnStop; 21 | 22 | UFUNCTION(BlueprintCallable) 23 | void Start(); 24 | 25 | UFUNCTION(BlueprintCallable) 26 | void Stop(); 27 | 28 | protected: 29 | void BeginPlay() override; 30 | 31 | void EndPlay(EEndPlayReason::Type EndPlayReason) override; 32 | 33 | private: 34 | UPROPERTY(EditAnywhere) 35 | float Rate = 0.2f; 36 | 37 | UPROPERTY(EditAnywhere) 38 | float FirstDelay = 0.f; 39 | 40 | FTimerHandle Handle; 41 | }; 42 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/BinaryOperation.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operation.h" 7 | #include "BinaryOperation.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS(BlueprintType, Abstract, Blueprintable) 13 | class UTILITYAI_API UBinaryOperation : public UOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | friend class UUtilityAIStatics; 18 | 19 | public: 20 | void GetPredicatesRecursively(FPredicatesContainerRef Predicates) override; 21 | 22 | protected: 23 | UFUNCTION(BlueprintCallable) 24 | UExpression* First() const; 25 | 26 | UFUNCTION(BlueprintCallable) 27 | UExpression* Second() const; 28 | 29 | UFUNCTION(BlueprintCallable) 30 | bool FirstResult(const TScriptInterface& Agent) const; 31 | 32 | UFUNCTION(BlueprintCallable) 33 | bool SecondResult(const TScriptInterface& Agent) const; 34 | 35 | private: 36 | UPROPERTY() 37 | UExpression* Operand1; 38 | 39 | UPROPERTY() 40 | UExpression* Operand2; 41 | 42 | void Init(UExpression* F, UExpression* S); 43 | }; 44 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Actions/Action.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Action.h" 4 | #include "Agent.h" 5 | #include "Condition.h" 6 | #include "UtilityAIConstants.h" 7 | 8 | UAction::UAction() 9 | { 10 | BaseValue = UUtilityAIConstants::MinActionRating(); 11 | } 12 | 13 | float UAction::Evaluate(const TScriptInterface& Agent) 14 | { 15 | auto Result = UUtilityAIConstants::MinActionRating(); 16 | for (auto& Condition : Conditions) 17 | { 18 | const auto Value = Condition.Evaluate(Agent); 19 | OnConditionEvaluated.Broadcast(Condition.GetName(), Value); 20 | Result += Value; 21 | } 22 | Result = FMath::Clamp(Result, UUtilityAIConstants::MinActionRating(), UUtilityAIConstants::MaxActionRating()); 23 | OnEvaluated.Broadcast(GetName(), Result); 24 | return Result; 25 | } 26 | 27 | void UAction::Run_Implementation(const TScriptInterface& Agent) const 28 | { 29 | OnRun.Broadcast(GetName()); 30 | } 31 | 32 | bool UAction::IgnoreIfCalledTwice() const 33 | { 34 | return bIgnoreIfCalledTwice; 35 | } 36 | 37 | const TArray& UAction::GetConditions() const 38 | { 39 | return Conditions; 40 | } 41 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Components/UtilityAIBrainComponent.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "Components/ActorComponent.h" 6 | #include "UtilityAIBrainComponent.generated.h" 7 | 8 | class UBrainAsset; 9 | UCLASS(ClassGroup=(UtilityAI), meta=(BlueprintSpawnableComponent, DisplayName="Utility AI Brain"), Blueprintable) 10 | class UTILITYAI_API UUtilityAIBrainComponent : public UActorComponent 11 | { 12 | GENERATED_BODY() 13 | 14 | DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBrainSignature); 15 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FActionSignature, FString, ActionName); 16 | 17 | public: 18 | UUtilityAIBrainComponent(); 19 | 20 | FBrainSignature OnBeforeAct; 21 | FBrainSignature OnAfterAct; 22 | 23 | FActionSignature OnActionRun; 24 | 25 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent) 26 | void Act() const; 27 | virtual void Act_Implementation() const; 28 | 29 | UFUNCTION(BlueprintCallable) 30 | UBrainAsset* GetBrainAsset() const; 31 | 32 | protected: 33 | void BeginPlay() override; 34 | 35 | private: 36 | UPROPERTY(EditAnywhere) 37 | TSubclassOf BrainAssetClass; 38 | 39 | UPROPERTY() 40 | UBrainAsset* Asset; 41 | }; 42 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/TernaryOperation.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "TernaryOperation.h" 4 | 5 | void UTernaryOperation::GetPredicatesRecursively(FPredicatesContainerRef Predicates) 6 | { 7 | Operand1->GetPredicatesRecursively(Predicates); 8 | Operand2->GetPredicatesRecursively(Predicates); 9 | Operand3->GetPredicatesRecursively(Predicates); 10 | } 11 | 12 | UExpression* UTernaryOperation::First() const 13 | { 14 | return Operand1; 15 | } 16 | 17 | UExpression* UTernaryOperation::Second() const 18 | { 19 | return Operand2; 20 | } 21 | 22 | UExpression* UTernaryOperation::Third() const 23 | { 24 | return Operand3; 25 | } 26 | 27 | bool UTernaryOperation::FirstResult(const TScriptInterface& Agent) const 28 | { 29 | return First()->Evaluate(Agent); 30 | } 31 | 32 | bool UTernaryOperation::SecondResult(const TScriptInterface& Agent) const 33 | { 34 | return Second()->Evaluate(Agent); 35 | } 36 | 37 | bool UTernaryOperation::ThirdResult(const TScriptInterface& Agent) const 38 | { 39 | return Third()->Evaluate(Agent); 40 | } 41 | 42 | void UTernaryOperation::Init(UExpression* F, UExpression* S, UExpression* T) 43 | { 44 | Operand1 = F; 45 | Operand2 = S; 46 | Operand3 = T; 47 | } 48 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/TernaryOperation.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operation.h" 7 | #include "TernaryOperation.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS(BlueprintType, Abstract, Blueprintable) 13 | class UTILITYAI_API UTernaryOperation : public UOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | friend class UUtilityAIStatics; 18 | 19 | public: 20 | void GetPredicatesRecursively(FPredicatesContainerRef Predicates) override; 21 | 22 | protected: 23 | UFUNCTION(BlueprintCallable) 24 | UExpression* First() const; 25 | 26 | UFUNCTION(BlueprintCallable) 27 | UExpression* Second() const; 28 | 29 | UFUNCTION(BlueprintCallable) 30 | UExpression* Third() const; 31 | 32 | UFUNCTION(BlueprintCallable) 33 | bool FirstResult(const TScriptInterface& Agent) const; 34 | 35 | UFUNCTION(BlueprintCallable) 36 | bool SecondResult(const TScriptInterface& Agent) const; 37 | 38 | UFUNCTION(BlueprintCallable) 39 | bool ThirdResult(const TScriptInterface& Agent) const; 40 | 41 | private: 42 | UPROPERTY() 43 | UExpression* Operand1; 44 | 45 | UPROPERTY() 46 | UExpression* Operand2; 47 | 48 | UPROPERTY() 49 | UExpression* Operand3; 50 | 51 | void Init(UExpression* F, UExpression* S, UExpression* T); 52 | }; 53 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Operations/MultiOperation.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "MultiOperation.h" 4 | 5 | void UMultiOperation::GetPredicatesRecursively(FPredicatesContainerRef Predicates) 6 | { 7 | for (const auto& Expr : Operands()) 8 | { 9 | Expr->GetPredicatesRecursively(Predicates); 10 | } 11 | } 12 | 13 | UExpression* UMultiOperation::Nth(int N) const 14 | { 15 | return Ops[N]; 16 | } 17 | 18 | const TArray& UMultiOperation::Operands() const 19 | { 20 | return Ops; 21 | } 22 | 23 | bool UMultiOperation::NthResult(const TScriptInterface& Agent, int N) const 24 | { 25 | return Nth(N)->Evaluate(Agent); 26 | } 27 | 28 | TArray UMultiOperation::OperandsResults(const TScriptInterface& Agent) const 29 | { 30 | TArray Results; 31 | for (const auto Op : Ops) 32 | { 33 | const auto Evaluated = Op->Evaluate(Agent); 34 | Results.Add(Evaluated); 35 | } 36 | return Results; 37 | } 38 | 39 | int UMultiOperation::NthArg(const int N) const 40 | { 41 | return Args[N]; 42 | } 43 | 44 | int UMultiOperation::ArgsNum() const 45 | { 46 | return Args.Num(); 47 | } 48 | 49 | const TArray& UMultiOperation::Arguments() const 50 | { 51 | return Args; 52 | } 53 | 54 | void UMultiOperation::Init(const TArray& O, const TArray& A) 55 | { 56 | Ops = O; 57 | Args = A; 58 | } 59 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Operations/MultiOperation.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Operation.h" 7 | #include "MultiOperation.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS(BlueprintType, Abstract, Blueprintable) 13 | class UTILITYAI_API UMultiOperation : public UOperation 14 | { 15 | GENERATED_BODY() 16 | 17 | friend class UUtilityAIStatics; 18 | 19 | public: 20 | void GetPredicatesRecursively(FPredicatesContainerRef Predicates) override; 21 | 22 | protected: 23 | 24 | // Operands 25 | 26 | UFUNCTION(BlueprintCallable) 27 | UExpression* Nth(int N) const; 28 | 29 | UFUNCTION(BlueprintCallable) 30 | const TArray& Operands() const; 31 | 32 | // Results 33 | 34 | UFUNCTION(BlueprintCallable) 35 | bool NthResult(const TScriptInterface& Agent, int N) const; 36 | 37 | UFUNCTION(BlueprintCallable) 38 | TArray OperandsResults(const TScriptInterface& Agent) const; 39 | 40 | // Arguments 41 | 42 | UFUNCTION(BlueprintCallable) 43 | int NthArg(int N) const; 44 | 45 | UFUNCTION(BlueprintCallable) 46 | int ArgsNum() const; 47 | 48 | UFUNCTION(BlueprintCallable) 49 | const TArray& Arguments() const; 50 | 51 | private: 52 | UPROPERTY() 53 | TArray Ops; 54 | 55 | TArray Args; 56 | 57 | void Init(const TArray& O, const TArray& A); 58 | }; 59 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Actions/Action.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Condition.h" 7 | #include "Action.generated.h" 8 | 9 | class IAgent; 10 | /** 11 | * 12 | */ 13 | UCLASS(BlueprintType, Blueprintable, Abstract) 14 | class UTILITYAI_API UAction : public UObject 15 | { 16 | GENERATED_BODY() 17 | 18 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FActionSignature, FString, ActionName, float, Value); 19 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FActionRunSignature, FString, ActionName); 20 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FConditionSignature, FString, ConditionName, float, Value); 21 | 22 | public: 23 | UAction(); 24 | 25 | FActionSignature OnEvaluated; 26 | 27 | FActionRunSignature OnRun; 28 | 29 | FConditionSignature OnConditionEvaluated; 30 | 31 | UFUNCTION(BlueprintCallable) 32 | float Evaluate(const TScriptInterface& Agent); 33 | 34 | UFUNCTION(BlueprintNativeEvent) 35 | void Run(const TScriptInterface& Agent) const; 36 | virtual void Run_Implementation(const TScriptInterface& Agent) const; 37 | 38 | UFUNCTION(BlueprintCallable) 39 | bool IgnoreIfCalledTwice() const; 40 | 41 | UFUNCTION(BlueprintCallable) 42 | const TArray& GetConditions() const; 43 | 44 | private: 45 | UPROPERTY(EditAnywhere, AdvancedDisplay) 46 | float BaseValue; 47 | 48 | UPROPERTY(EditAnywhere, AdvancedDisplay) 49 | bool bIgnoreIfCalledTwice = false; 50 | 51 | UPROPERTY(EditAnywhere) 52 | TArray Conditions; 53 | }; 54 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Debugging/UtilityAIDebuggerComponent.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Components/ActorComponent.h" 7 | #include "DebuggerSettings.h" 8 | #include "UtilityAIDebuggerComponent.generated.h" 9 | 10 | class UUtilityAIBrainComponent; 11 | UCLASS(ClassGroup=(UtilityAI), meta=(BlueprintSpawnableComponent), DisplayName="Utility AI Debugger") 12 | class UTILITYAI_API UUtilityAIDebuggerComponent : public UActorComponent 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | // Sets default values for this component's properties 18 | UUtilityAIDebuggerComponent(); 19 | 20 | protected: 21 | // Called when the game starts 22 | void BeginPlay() override; 23 | 24 | // Called every frame 25 | void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; 26 | 27 | private: 28 | UPROPERTY(EditAnywhere) 29 | bool bIsDebugEnabled = true; 30 | 31 | UPROPERTY(EditAnywhere) 32 | FDebuggerSettings Settings; 33 | 34 | UPROPERTY(VisibleAnywhere) 35 | TMap State; 36 | 37 | UPROPERTY(VisibleAnywhere) 38 | TMap ActionsState; 39 | 40 | UPROPERTY(VisibleAnywhere) 41 | TMap PredicatesState; 42 | 43 | UPROPERTY() 44 | UUtilityAIBrainComponent* BrainComponent; 45 | 46 | UFUNCTION() 47 | void ReactOnActionRun(FString ActionName); 48 | 49 | UFUNCTION() 50 | void ReactOnActionEvaluated(FString ActionName, float Value); 51 | 52 | UFUNCTION() 53 | void ReactOnPredicateEvaluated(FString PredicateName, bool Success); 54 | 55 | void StartDebugging(); 56 | void BindBrainComponent(); 57 | void BindActions(); 58 | void BindPredicates(); 59 | 60 | const FDebuggerSettings& GetSettings() const; 61 | 62 | FString StripName(const FString& Name) const; 63 | }; 64 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Statics/UtilityAIStatics.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Kismet/BlueprintFunctionLibrary.h" 7 | #include "UtilityAIStatics.generated.h" 8 | 9 | class UPredicate; 10 | class UMultiOperation; 11 | class UTernaryOperation; 12 | class UBinaryOperation; 13 | class UUnaryOperation; 14 | class UExpression; 15 | class AAIController; 16 | class IAgent; 17 | /** 18 | * 19 | */ 20 | UCLASS() 21 | class UTILITYAI_API UUtilityAIStatics : public UBlueprintFunctionLibrary 22 | { 23 | GENERATED_BODY() 24 | 25 | public: 26 | // Creating and setting up base objects 27 | 28 | UFUNCTION(Category="Utility AI|Statics", BlueprintPure) 29 | static UExpression* CreateUnaryOperation(TSubclassOf Class, UExpression* Operand); 30 | 31 | UFUNCTION(Category="Utility AI|Statics", BlueprintPure) 32 | static UExpression* CreateBinaryOperation(TSubclassOf Class, UExpression* Operand1, UExpression* Operand2); 33 | 34 | UFUNCTION(Category="Utility AI|Statics", BlueprintPure) 35 | static UExpression* CreateTernaryOperation(TSubclassOf Class, UExpression* Operand1, UExpression* Operand2, UExpression* Operand3); 36 | 37 | UFUNCTION(Category="Utility AI|Statics", BlueprintPure) 38 | static UExpression* CreateMultiOperation(TSubclassOf Class, TArray Operands, TArray Arguments); 39 | 40 | UFUNCTION(Category="Utility AI|Statics", BlueprintPure) 41 | static UExpression* CreatePredicate(TSubclassOf Class); 42 | 43 | // IAgent utility functions 44 | 45 | UFUNCTION(Category = "Utility AI|Statics", BlueprintPure) 46 | static AAIController* AsAIController(const TScriptInterface& Agent); 47 | 48 | UFUNCTION(Category = "Utility AI|Statics", BlueprintPure) 49 | static AActor* AsActor(const TScriptInterface& Agent); 50 | 51 | private: 52 | static UObject* GetOuter(); 53 | }; 54 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Statics/UtilityAIStatics.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "UtilityAIStatics.h" 4 | #include "Expression.h" 5 | #include "UnaryOperation.h" 6 | #include "BinaryOperation.h" 7 | #include "TernaryOperation.h" 8 | #include "MultiOperation.h" 9 | #include "Predicate.h" 10 | #include "Agent.h" 11 | #include "AIController.h" 12 | 13 | UExpression* UUtilityAIStatics::CreateUnaryOperation(const TSubclassOf Class, UExpression* Operand) 14 | { 15 | const auto Op = NewObject(GetOuter(), Class, TEXT("Unary operation")); 16 | check(Op); 17 | Op->Init(Operand); 18 | return Op; 19 | } 20 | 21 | UExpression* UUtilityAIStatics::CreateBinaryOperation(const TSubclassOf Class, UExpression* Operand1, UExpression* Operand2) 22 | { 23 | const auto Op = NewObject(GetOuter(), Class, TEXT("Binary operation")); 24 | check(Op); 25 | Op->Init(Operand1, Operand2); 26 | return Op; 27 | } 28 | 29 | UExpression* UUtilityAIStatics::CreateTernaryOperation(const TSubclassOf Class, UExpression* Operand1, UExpression* Operand2, UExpression* Operand3) 30 | { 31 | const auto Op = NewObject(GetOuter(), Class, TEXT("Ternary operation")); 32 | check(Op); 33 | Op->Init(Operand1, Operand2, Operand3); 34 | return Op; 35 | } 36 | 37 | UExpression* UUtilityAIStatics::CreateMultiOperation(const TSubclassOf Class, const TArray Operands, const TArray Arguments) 38 | { 39 | const auto Op = NewObject(GetOuter(), Class, TEXT("Multi operation")); 40 | check(Op); 41 | Op->Init(Operands, Arguments); 42 | return Op; 43 | } 44 | 45 | UExpression* UUtilityAIStatics::CreatePredicate(const TSubclassOf Class) 46 | { 47 | return NewObject(GetOuter(), Class, TEXT("Predicate")); 48 | } 49 | 50 | AAIController* UUtilityAIStatics::AsAIController(const TScriptInterface& Agent) 51 | { 52 | return Cast(Agent.GetObject()); 53 | } 54 | 55 | AActor* UUtilityAIStatics::AsActor(const TScriptInterface& Agent) 56 | { 57 | return Cast(Agent.GetObject()); 58 | } 59 | 60 | UObject* UUtilityAIStatics::GetOuter() 61 | { 62 | return Cast(GetTransientPackage()); 63 | } 64 | -------------------------------------------------------------------------------- /Source/UtilityAI/Public/Brains/BrainAsset.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "BrainAsset.generated.h" 7 | 8 | class IAgent; 9 | class UAction; 10 | /** 11 | * 12 | */ 13 | UCLASS(BlueprintType, Abstract, Blueprintable) 14 | class UTILITYAI_API UBrainAsset : public UObject 15 | { 16 | GENERATED_BODY() 17 | 18 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FActionSignature, FString, ActionName, float, Value); 19 | 20 | public: 21 | FActionSignature OnActionRanked; 22 | FActionSignature OnActionSelected; 23 | FActionSignature OnLowRankedActionSkipped; 24 | FActionSignature OnRepeatingActionSkipped; 25 | FActionSignature OnOtherActionsSkipped; 26 | 27 | UFUNCTION(BlueprintCallable) 28 | UAction* SelectAction(const TScriptInterface& Agent); 29 | 30 | UFUNCTION(BlueprintCallable) 31 | const TArray& GetActions(); 32 | 33 | private: 34 | UPROPERTY(EditAnywhere, AdvancedDisplay, meta=(InlineEditConditionToggle)) 35 | bool bHasMinValueToAct = false; 36 | 37 | UPROPERTY(EditAnywhere, AdvancedDisplay, meta=(EditCondition=bHasMinValueToAct)) 38 | float MinValueToAct = 0.05f; 39 | 40 | UPROPERTY(EditAnywhere, AdvancedDisplay, meta = (InlineEditConditionToggle)) 41 | bool bHasSkipOtherActionsValue = false; 42 | 43 | UPROPERTY(EditAnywhere, AdvancedDisplay, meta = (EditCondition = bHasSkipOtherActionsValue)) 44 | float SkipOtherActionsValue = 0.95f; 45 | 46 | UPROPERTY(EditAnywhere) 47 | TArray> ActionClasses; 48 | 49 | UPROPERTY(EditAnywhere, AdvancedDisplay) 50 | TArray> PreActionClasses; 51 | 52 | UPROPERTY(EditAnywhere, AdvancedDisplay) 53 | TArray> PostActionClasses; 54 | 55 | TArray Actions; 56 | TArray PreActions; 57 | TArray PostActions; 58 | 59 | UPROPERTY() 60 | UAction* LastAction; 61 | 62 | void CreateActions(); 63 | void ExecutePreActions(const TScriptInterface& Agent) const; 64 | void ExecutePostActions(const TScriptInterface& Agent) const; 65 | 66 | bool ShouldSkipOtherActions(float Value) const; 67 | bool ShouldSkipRepeatingAction(UAction* Action) const; 68 | bool ShouldSkipLowRankedAction(float Value) const; 69 | bool ShouldCreateActions() const; 70 | 71 | UAction* GetBestEvaluatedAction(const TScriptInterface& Agent); 72 | }; 73 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Brains/BrainAsset.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "BrainAsset.h" 4 | #include "Action.h" 5 | #include "UtilityAIConstants.h" 6 | #include "UtilityAI.h" 7 | 8 | bool UBrainAsset::ShouldSkipOtherActions(const float Value) const 9 | { 10 | return bHasSkipOtherActionsValue && Value > SkipOtherActionsValue; 11 | } 12 | 13 | bool UBrainAsset::ShouldSkipRepeatingAction(UAction* Action) const 14 | { 15 | return Action == LastAction 16 | && Action 17 | && Action->IgnoreIfCalledTwice(); 18 | } 19 | 20 | bool UBrainAsset::ShouldSkipLowRankedAction(const float Value) const 21 | { 22 | return bHasMinValueToAct && MinValueToAct > Value; 23 | } 24 | 25 | bool UBrainAsset::ShouldCreateActions() const 26 | { 27 | return Actions.Num() == 0; 28 | } 29 | 30 | UAction* UBrainAsset::GetBestEvaluatedAction(const TScriptInterface& Agent) 31 | { 32 | UAction* BestAction = nullptr; 33 | auto BestValue = UUtilityAIConstants::AbsoluteMin(); 34 | for (const auto Action : Actions) 35 | { 36 | check(Action); 37 | const auto Value = Action->Evaluate(Agent); 38 | OnActionRanked.Broadcast(Action->GetName(), Value); 39 | if (Value > BestValue) 40 | { 41 | BestValue = Value; 42 | BestAction = Action; 43 | if (ShouldSkipOtherActions(BestValue)) 44 | { 45 | OnOtherActionsSkipped.Broadcast(BestAction->GetName(), Value); 46 | break; 47 | } 48 | } 49 | } 50 | if (BestAction) 51 | { 52 | OnActionSelected.Broadcast(BestAction->GetName(), BestValue); 53 | if (ShouldSkipRepeatingAction(BestAction)) 54 | { 55 | OnRepeatingActionSkipped.Broadcast(BestAction->GetName(), BestValue); 56 | return nullptr; 57 | } 58 | if (ShouldSkipLowRankedAction(BestValue)) 59 | { 60 | OnLowRankedActionSkipped.Broadcast(BestAction->GetName(), BestValue); 61 | LastAction = nullptr; 62 | return nullptr; 63 | } 64 | } 65 | else 66 | { 67 | OnActionSelected.Broadcast("None", 0.f); 68 | } 69 | LastAction = BestAction; 70 | return BestAction; 71 | } 72 | 73 | UAction* UBrainAsset::SelectAction(const TScriptInterface& Agent) 74 | { 75 | if (ShouldCreateActions()) 76 | { 77 | CreateActions(); 78 | } 79 | ExecutePreActions(Agent); 80 | const auto BestAction = GetBestEvaluatedAction(Agent); 81 | ExecutePostActions(Agent); 82 | return BestAction; 83 | } 84 | 85 | void UBrainAsset::CreateActions() 86 | { 87 | for (const auto& Class : ActionClasses) 88 | { 89 | Actions.Add(NewObject(this, Class)); 90 | } 91 | for (const auto& Class : PreActionClasses) 92 | { 93 | PreActions.Add(NewObject(this, Class)); 94 | } 95 | for (const auto& Class : PostActionClasses) 96 | { 97 | PostActions.Add(NewObject(this, Class)); 98 | } 99 | } 100 | 101 | void UBrainAsset::ExecutePreActions(const TScriptInterface& Agent) const 102 | { 103 | for (const auto Action : PreActions) 104 | { 105 | Action->Run(Agent); 106 | } 107 | } 108 | 109 | void UBrainAsset::ExecutePostActions(const TScriptInterface& Agent) const 110 | { 111 | for (const auto Action : PostActions) 112 | { 113 | Action->Run(Agent); 114 | } 115 | } 116 | 117 | const TArray& UBrainAsset::GetActions() 118 | { 119 | if (ShouldCreateActions()) 120 | { 121 | CreateActions(); 122 | } 123 | return Actions; 124 | } 125 | -------------------------------------------------------------------------------- /Source/UtilityAI/Private/Debugging/UtilityAIDebuggerComponent.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "Debugging/UtilityAIDebuggerComponent.h" 4 | #include "GameFramework/Actor.h" 5 | #include "UtilityAIBrainComponent.h" 6 | #include "UtilityAI.h" 7 | #include "BrainAsset.h" 8 | #include "Action.h" 9 | #include "Predicate.h" 10 | #include "Expression.h" 11 | 12 | // Sets default values for this component's properties 13 | UUtilityAIDebuggerComponent::UUtilityAIDebuggerComponent() 14 | { 15 | PrimaryComponentTick.bCanEverTick = true; 16 | } 17 | 18 | // Called when the game starts 19 | void UUtilityAIDebuggerComponent::BeginPlay() 20 | { 21 | Super::BeginPlay(); 22 | if (const auto Component = GetOwner()->GetComponentByClass(UUtilityAIBrainComponent::StaticClass())) 23 | { 24 | BrainComponent = Cast(Component); 25 | } 26 | StartDebugging(); 27 | } 28 | 29 | // Called every frame 30 | void UUtilityAIDebuggerComponent::TickComponent(const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) 31 | { 32 | Super::TickComponent(DeltaTime, TickType, ThisTickFunction); 33 | } 34 | 35 | void UUtilityAIDebuggerComponent::ReactOnActionRun(FString ActionName) 36 | { 37 | State.Emplace(TEXT("Active action"), ActionName); 38 | } 39 | 40 | void UUtilityAIDebuggerComponent::ReactOnActionEvaluated(FString ActionName, float Value) 41 | { 42 | if (GetSettings().bStripActionNames) 43 | { 44 | ActionName = StripName(ActionName); 45 | } 46 | ActionsState.Emplace(ActionName, Value); 47 | } 48 | 49 | void UUtilityAIDebuggerComponent::ReactOnPredicateEvaluated(FString PredicateName, bool Success) 50 | { 51 | if (GetSettings().bStripPredicateNames) 52 | { 53 | PredicateName = StripName(PredicateName); 54 | } 55 | PredicatesState.Emplace(PredicateName, Success); 56 | } 57 | 58 | void UUtilityAIDebuggerComponent::BindBrainComponent() 59 | { 60 | BrainComponent->OnActionRun.AddDynamic(this, &UUtilityAIDebuggerComponent::ReactOnActionRun); 61 | } 62 | 63 | void UUtilityAIDebuggerComponent::BindActions() 64 | { 65 | const auto& Actions = BrainComponent->GetBrainAsset()->GetActions(); 66 | for (const auto Action : Actions) 67 | { 68 | Action->OnEvaluated.AddDynamic(this, &UUtilityAIDebuggerComponent::ReactOnActionEvaluated); 69 | } 70 | } 71 | 72 | void UUtilityAIDebuggerComponent::BindPredicates() 73 | { 74 | const auto& Actions = BrainComponent->GetBrainAsset()->GetActions(); 75 | UExpression::FPredicatesContainer Predicates; 76 | for (const auto Action : Actions) 77 | { 78 | const auto& Conditions = Action->GetConditions(); 79 | for (const auto& Condition : Conditions) 80 | { 81 | Condition.GetPredicate(BrainComponent)->GetPredicatesRecursively(Predicates); 82 | } 83 | } 84 | for (auto& Predicate : Predicates) 85 | { 86 | Predicate->OnEvaluated.AddDynamic(this, &UUtilityAIDebuggerComponent::ReactOnPredicateEvaluated); 87 | } 88 | } 89 | 90 | const FDebuggerSettings& UUtilityAIDebuggerComponent::GetSettings() const 91 | { 92 | return Settings; 93 | } 94 | 95 | FString UUtilityAIDebuggerComponent::StripName(const FString& Name) const 96 | { 97 | auto Index = Name.Len() - 1; 98 | Name.FindLastChar('_', Index); 99 | --Index; 100 | Name.FindLastChar('_', Index); 101 | return Name.Left(Index-2); 102 | } 103 | 104 | void UUtilityAIDebuggerComponent::StartDebugging() 105 | { 106 | if (BrainComponent == nullptr) 107 | { 108 | UE_LOG(UtilityAI_Debugging, Warning, TEXT("There is no Utility AI Brain Component found")); 109 | return; 110 | } 111 | BindBrainComponent(); 112 | BindActions(); 113 | BindPredicates(); 114 | } 115 | --------------------------------------------------------------------------------