斯坦福CS193U-虚幻4C++课程学习笔记(9)

Lecture 10 - AI Overview

Unreal AI System

Tips:

  • 需要添加"AIModule"至build文件中

  • 当build时遇到unresolved external symbol这个问题的时候,可以通过查找缺少的类文件在哪个路径下,再将该模块添加至build中即可修复

Navigation Mesh

提供AI可以移动区域的数据

Behavior Tree

AI的大脑,从上往下从左至右执行

Node

  • Selector - 选择一个子节点 (从左至右分析)

  • 检测Decorators是否允许执行

  • Sequence - 从左至右顺序执行子节点

  • 当任何'failure'发生时取消sequence

  • Task - 行为

  • Service - 对于后台任务重复执行

  • Decorator - 条件检测,执行流控制

  • Blackboard Based Condition - 检查黑板的基础键值是否满足条件

  • Observer aborts

  • Self - 不满足条件时,将该节点和其子树全部取消执行

  • Low Priority - 当条件满足时,取消执行其他节点而立即执行该节点

  • Both - 结合上述2点

Blackboard

AI的存储数据的地方

Environment Query System

基于测试的对于物体/地点的空间查询

PawnSensing & AIPerception

AI的感知系统

Debugging Tools

  • Gameplay Debugger - 游戏内按下'键

  • Visual Logger - Window > Developer Tools > Visual Logger

项目代码

GitHub: https://github.com/yufeige4/ActionRoguelike

Tips: Implements<UObject版的Interface>(),而使用时应使用Interface版的Interface

  • 实现简单的范围判定并追击的AI

// GBTService_RangeCheck.h

UCLASS()
class ACTIONROGUELIKE_API UGBTService_RangeCheck : public UBTService
{
GENERATED_BODY()

protected:
virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;

UPROPERTY(EditAnywhere, Category = "AI")
FBlackboardKeySelector Key_TargetActor;

UPROPERTY(EditAnywhere, Category = "AI")
FBlackboardKeySelector Key_AttackRange;

UPROPERTY(EditAnywhere, Category = "AI")
FBlackboardKeySelector Key_InsideAttackRange;

};
// GBTService_RangeCheck.cpp

void UGBTService_RangeCheck::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
	Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);

	UBlackboardComponent* MyBB = OwnerComp.GetBlackboardComponent();
	AAIController* MyController = OwnerComp.GetAIOwner();
	
	if(ensure(MyPawn))
		{
			if(TargetActor)
			{
				float AttackRange = MyBB->GetValueAsFloat(Key_AttackRange.SelectedKeyName);
				float Distance = FVector::Distance(TargetActor->GetActorLocation(),MyPawn->GetActorLocation());

				bool InsideAttackRange = Distance <= AttackRange;
				MyBB->SetValueAsBool(Key_InsideAttackRange.SelectedKeyName,InsideAttackRange);
			}
		}
}
// GAIController.h

class UBehaviorTree;

UCLASS()
class ACTIONROGUELIKE_API AGAIController : public AAIController
{
	GENERATED_BODY()

protected:
	virtual void BeginPlay() override;

	UPROPERTY(EditDefaultsOnly, Category = "AI")
	UBehaviorTree* BehaviorTree;

	virtual void OnPossess(APawn* InPawn) override;
};
// GAIController.cpp

void AGAIController::BeginPlay()
{
	Super::BeginPlay();
	APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(this,0);
	UBlackboardComponent* MyBB = GetBlackboardComponent();
	if(ensure(MyBB)&ensure(PlayerPawn))
	{
		MyBB->SetValueAsObject("TargetActor",PlayerPawn);
	}
}

void AGAIController::OnPossess(APawn* InPawn)
{
	Super::OnPossess(InPawn);
	RunBehaviorTree(BehaviorTree);
	
	UBlackboardComponent* MyBB = GetBlackboardComponent();
	

	if(ensure(MyBB))
	{
        // 判断是否实现应判断UObject版
		if(InPawn->Implements<UGAICharacterInterface>())
		{
            // 而使用接口函数时应使用Interface版
			float AttackRange = IGAICharacterInterface::Execute_GetAttackRange(InPawn);
			MyBB->SetValueAsFloat("AttackRange",AttackRange);
		}
	}
}
// GAICharacterInterface.h

UINTERFACE(MinimalAPI)
class UGAICharacterInterface : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */
class ACTIONROGUELIKE_API IGAICharacterInterface
{
	GENERATED_BODY()

	// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	float GetAttackRange();
	
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值