11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI

EQS优化,让AI知道什么地方不能走

首先进行小修改,创建一个新的AIEQS

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第1张图片

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第2张图片

新建一个测试pawn

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第3张图片

把测试pawn放入场景内,在eqs中放入我们写的eqs任务,使用模拟游戏,就可以直接可视化eqs的选择坐标点

https://docs.unrealengine.com/5.0/en-US/environment-query-testing-pawn-in-unreal-engine/

这样调整eqs的时候可以更直观

添加距离检测,防止ai过于靠近pawn

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第4张图片

修改为最小距离,最小距离为1000,并且调整Point Per Ring

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第5张图片

如何防止AI导航到方块内

使用NavModifierVolume

在EQS内修改AI范围

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第6张图片

也可以使用查询路径来判断AI在哪些方面不能进行行走,但是非常吃资源

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第7张图片

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第8张图片

自定义游戏模式

创建GameClass类

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第9张图片

这里我也不放截图,直接复制代码

gamebase .h

// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "AI/SAICharacter.h" #include "EnvironmentQuery/EnvQueryTypes.h" #include "GameFramework/GameModeBase.h" #include "SGameModeBase.generated.h" class UEnvQueryInstanceBlueprintWrapper; class UEnvQuery; /** * */ UCLASS() class ACTIONROUGELIKE_API ASGameModeBase : public AGameModeBase { GENERATED_BODY() protected: UPROPERTY(EditAnywhere,Category="AI") TSubclassOf MinionClass; UPROPERTY(EditAnywhere,Category="AI") UCurveFloat* DifficultyCurve; UPROPERTY(EditAnywhere,Category="AI") UEnvQuery* SpawnBotQuery ; FTimerHandle TimerHandle_SpawnBots; //EEnvQueryStatus::Type枚举类型 UFUNCTION() void OnQueryCompleted( UEnvQueryInstanceBlueprintWrapper* QueryInstance, EEnvQueryStatus::Type QueryStatus); UPROPERTY(EditAnywhere,Category="AI") float SpawnTimerInterval; UFUNCTION() void SpawnTimerElapsed(); public: ASGameModeBase(); virtual void StartPlay() override;; };

.cpp

// Fill out your copyright notice in the Description page of Project Settings. #include "SGameModeBase.h" #include "EnvironmentQuery/EnvQueryManager.h" #include "EnvironmentQuery/EnvQueryTypes.h" #include "EnvironmentQuery/EnvQueryInstanceBlueprintWrapper.h" #include "AI/SAICharacter.h" #include "SAttributeComponent.h" #include "EngineUtils.h" ASGameModeBase::ASGameModeBase() { SpawnTimerInterval =2.0f; } void ASGameModeBase::StartPlay() { //继承Base的StartPlay Super::StartPlay(); /*我们正在从我们的时间管理器对象创建一个计时器。 然后我们注册这个回调以使用我们的定时器句柄。 然后我们分配一个回调方法,在倒计时结束时触发。 最后我们设置倒计时时间为SpawnTimerInterval秒。*/ GetWorldTimerManager().SetTimer(TimerHandle_SpawnBots,this,&ASGameModeBase::SpawnTimerElapsed,SpawnTimerInterval,true); } void ASGameModeBase::SpawnTimerElapsed() { //执行EQS查询,在全局搜索内查询RunEQSQuery可以找到EnvQueryManage.cpp这个文件,在这个文件内可以找到这个函数 UEnvQueryInstanceBlueprintWrapper* QueryInstance = UEnvQueryManager::RunEQSQuery(this,SpawnBotQuery,this,EEnvQueryRunMode::RandomBest5Pct,nullptr); if(ensure(QueryInstance)) { //查询出一个节点后在5%这个误差内执行OnQueryCompleted这个函数 QueryInstance->GetOnQueryFinishedEvent().AddDynamic(this,&ASGameModeBase::OnQueryCompleted); } } //在玩家周围生成Bot void ASGameModeBase::OnQueryCompleted(UEnvQueryInstanceBlueprintWrapper* QueryInstance,EEnvQueryStatus::Type QueryStatus) { //确认是否生成 if(QueryStatus != EEnvQueryStatus::Success) { UE_LOG(LogTemp,Warning,TEXT("无法生成EQS:SpawnBotQuery!")) return; } //默认机器人为0 int32 NrOfAliveBots = 0; //判断机器人是否需要添加 for (TActorIterator It(GetWorld()); It; ++It) { ASAICharacter* Bot = *It; USAttributeComponent* AttributeComp = Cast(Bot->GetComponentByClass(USAttributeComponent::StaticClass())); if (ensure(AttributeComp) && AttributeComp->IsALive()) { NrOfAliveBots++; } } //当判断距离,UCurveFloat* DifficultyCurve可以理解成根据曲线数值判断 if(DifficultyCurve) { DifficultyCurve->GetFloatValue(GetWorld()->TimeSeconds); } //最大bot数量为10 float MaxBotCount =10.0f; //当数量过多的时候就return if(NrOfAliveBots>MaxBotCount) { return; } //获得EQS生成点的Locations,并添加到数组内 TArray Locations = QueryInstance->GetResultsAsLocations(); //判断数组内是否有第一个值 if(Locations.IsValidIndex(0)) { //生成Bot GetWorld()->SpawnActor(MinionClass,Locations[0],FRotator::ZeroRotator); } }

让AI在世界生成的时候自动添加AI控制器并执行

ASAICharacter::ASAICharacter() { // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; PawnSensingComp = CreateDefaultSubobject("PawnSensingComp"); //ai生成在世界内后自动执行控制器 AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned; }

##报错,无法间接强制转换

 

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第10张图片

查找资料后发现要手动引用

#include "EngineUtils.h"

这样就可以正确编译了

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第11张图片

难度提升,随着时间增多的AI

创建一条曲线

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第12张图片

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第13张图片

添加曲线

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第14张图片

最后把曲线放在Gamemode内

11月22日 EQS优化,让AI知道什么地方不能走,自定义游戏模式,让AI在玩家旁边生成,难度提升,随着时间增多的AI_第15张图片

效果图

你可能感兴趣的:(UE5,斯坦福C++,上课记录,人工智能,游戏)