【UE4C++-ActionRougelike-10】AI基础


【UE4C++-ActionRougelike-10】AI基础

1、AI系统

UE中内置了强大的人工智能(AI)系统,用于创建复杂的游戏角色和NPC行为。以下是虚幻引擎中的一些主要的AI系统和功能:

1.1AI控制器(AI Controller)

AI控制器是虚幻引擎中负责处理游戏角色和NPC行为的组件之一。用于控制角色的移动、旋转、寻路、攻击、对话等行为,并且可以与游戏角色或NPC关联。

1.2 黑板(Blackboard)

黑板是一种用于在AI系统中存储和共享数据的工具。它允许AI角色在运行时根据条件和情境来读取和写入数据,例如目标位置、目标状态、感知到的敌人等。

1.3 任务系统(Behavior Tree)

任务系统是一种基于行为树(Behavior Tree)的AI行为管理工具。行为树是一种树状结构,用于描述复杂的决策流程和行为序列。行为树系统可以通过可视化编辑器创建任务树,并与AI控制器关联。任务树可以用于管理角色的行为、决策、状态转换等。

1.4 感知系统(Perception System)

感知系统允许AI角色感知游戏世界中的其他角色、物体和环境信息。感知系统支持多种感知方式,例如视觉、听觉、碰触等,感知系统可以用于实现角色的警戒、追踪、攻击等行为。

1.5 寻路系统(Navigation System)

寻路系统允许AI角色在游戏世界中进行导航和移动。它可以生成路径、处理障碍、进行跳跃、避免碰撞等。虚幻引擎中的寻路系统支持多种导航方式,例如网格导航、点导航、复合导航等,并且可以与AI控制器、行为树等其他系统集成。

1.6 追踪器(EQS)

追踪器(Environment Query System,简称EQS)是虚幻引擎中用于在环境中进行查询和搜索的工具。EQS允许AI角色通过查询环境中的属性、特征、位置等信息来做出决策和行为选择。它可以用于实现角色的目标选择、目标评估、目标搜索等功能。

更详细内容参考官方文档

2、AI寻路角色

2.1 创建AI角色

以Character为父类创建AI角色类MyAICharacter,以MyAICharacter为父类创建蓝图类MinionRanged_BP,并设置相应Mesh和Animation。

设置AI角色的Mesh和AnimClass

2.2 设置导航

向世界添加导航网格边界体(Nav Mesh Bounds Volume),并覆盖整个Level。

导航网格边界体

2.3 寻路行为树

新建行为树MinionRanged_BT和黑板MinionRanged_BB。在黑板中设置数据,添加Object类型key,命名为TargetActor,Base Class选择Actor。TargetActor用作于AI跟踪目标。

黑板

在行为树中编写AI行动逻辑,设置Blackboard Asset为MinionRanged_BB,并在根节点下添加Sequence,添加MoveTo和Wait节点,并设置MoveTo对象为TargetActor。

行为树

2.4 设置寻路对象

以AIController为父类创建MyAIController类。

class ACTIONROGUELIKE_API AMyAIController : public AAIController
{
	GENERATED_BODY()
protected:
	
	UPROPERTY(EditDefaultsOnly, Category = "AI")
	UBehaviorTree* BehaviorTree;

	virtual void BeginPlay() override;
};

在MyAIController.cpp中,BeginPlay()开始后运行行为树,并且为Blackboard中的TargetActor赋值为玩家

void AMyAIController::BeginPlay()
{
	Super::BeginPlay();
	//运行行为树
	RunBehaviorTree(BehaviorTree);

	APawn* MyPawn = UGameplayStatics::GetPlayerPawn(this, 0);
	if (MyPawn)
	{
		//GetBlackboardComponent()->SetValueAsVector("MoveToLocation", MyPawn->GetActorLocation());
		//设置寻路目标Actor为玩家
		GetBlackboardComponent()->SetValueAsObject("TargetActor", MyPawn);
	}
}

最终效果演示如下:

AI寻路效果图

3、自定义检查攻击范围

3.1 创建行为树节点类

以BTService为父类创建行为树节点类MyBTService_CheckAttackRange

UCLASS()
class ACTIONROGUELIKE_API UMyBTService_CheckAttackRange : public UBTService
{
	GENERATED_BODY()
protected:
    //TickNode 函数是 UBTService 类中的一个虚函数,用于在行为树(Behavior Tree)节点每一帧被执行时调用。
	virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
	
	UPROPERTY(EditAnywhere, Category = "AI")
	FBlackboardKeySelector AttackRangeKey;
};

在MyBTService_CheckAttackRange.cpp中实现TickNode中的逻辑功能

// OwnerComp 参数获取了行为树组件的黑板组件
void UMyBTService_CheckAttackRange::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
	Super::TickNode(OwnerComp,NodeMemory,DeltaSeconds);
	UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent();
	if (ensure(BlackboardComp))
	{
        //从黑板组件中获取了名为 "TargetActor" 的黑板键对应的值
		AActor* TargetActor = Cast<AActor>(BlackboardComp->GetValueAsObject("TargetActor"));
		if (TargetActor)
		{
            //获取了行为树组件的 AI 控制器 AAIController 对象
			AAIController* MyAIController = OwnerComp.GetAIOwner();
			if (ensure(MyAIController)) 
			{
                //获取该 AI 控制器的控制的角色 APawn 对象
				APawn* AIPawn = MyAIController->GetPawn();
				if (ensure(AIPawn))
				{
                    //计算了TargetActor和AI角色的距离
					float DistanceTo = FVector::Distance(TargetActor->GetActorLocation(), AIPawn->GetActorLocation());
					//根据距离是否小于1000来设置一个名为 AttackRangeKey 的黑板键对应的布尔值
					bool bWithinRange = DistanceTo < 1000.0f;

					bool bHasLOS = false;
					if (bWithinRange)
					{
						bHasLOS = MyAIController->LineOfSightTo(TargetActor);
					}
					BlackboardComp->SetValueAsBool(AttackRangeKey.SelectedKeyName, (bWithinRange && bHasLOS));
				}
			}
		}
	}
}

注:这里编译前需要在模块构建脚本ActionRoguelike.Build.cs中添加对 “GameplayTasks” 模块的依赖。

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AIModule", "GameplayTasks" });

3.2 修改行为树

修改之前的行为树,Root根节点连接一个Selector节点,Selector节点是按顺序评估其子节点,并选择第一个返回成功 (Success) 或运行 (Running) 状态的子节点进行执行。如果子节点返回失败 (Failure) 状态,则继续评估下一个子节点。并同时调用上述定义的行为树节点CheckAttackRange获取WithinAttackRange的值。

行为树

Observer Aborts(观察者中止):是一种特殊的中止条件,用于控制行为树节点的执行。当观察者的条件满足时,Observer Aborts(Self) 模式下的节点将立即中止自身的执行,不再继续执行下面的子节点。(具体内容见总结部分)

当WithinAttackRange为真时继续执行,为假时终止。

设置装饰节点

最终效果图如下:

AI寻路+攻击距离效果图

4、总结

4.1 装饰器/黑板节点

黑板节点

通知观察者(Notify Observer)

  • 结果改变时(On Result Change):仅在条件改变时进行重新计算。
  • 值改变时(On Value Change):仅在观察到的黑板键改变时进行重新计算。

观察者中止(Observer Aborts)

  • 无(None):不中止执行。
  • 自身(Self):中止此节点自身和在其下运行的所有子树。
  • 低优先级(Lower Priority):中止此节点自身和在其下运行的所有子树。
  • 两者(Both):中止此节点自身和在其下运行的所有子树,以及此节点右侧的所有节点。

黑板键(Blackboard Key):装饰器将运行的黑板键。

键查询(Key Query)

  • 已经设置(Is Set):数值是否已设置?不为空或不为默认值,则条件节点返回 true;否则,返回 false
  • 尚未设置(Is Not Set):数值是否尚未设置?为空或为默认值,则条件节点返回 true;否则,返回 false

节点名称(Node Name):节点应该在行为树图表中显示的名称。


文章作者: Woilin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Woilin !
评论
  目录