【UE4 C++】 实现敌人追逐与攻击

效果展示

处在他的发现范围之外敌人是不会发现。
在这里插入图片描述
当走进他的发现范围之内的时候,他就会跑过来,
在这里插入图片描述
进行攻击。
在这里插入图片描述
现在还没有伤害。

C++ 文件

打开Built.cs文件,
找到:PublicDependencyModuleNames.AddRange
在之中添加"AIModule",增加AI相关的模块,这样系统才能识别我们调用的函数。

Enemy

创建继承Character类的Enemy类,因为不是玩家控制敌人的状态,而是计算机控制状态,所以需要在文件中声明敌人的状态:

UENUM(BlueprintType)
enum class EMoveStatus : uint8 {
	MS_Idle				UMETA(DisplayName = "Idle"),
	MS_MoveToTarget		UMETA(DisplayName = "MoveToTarget"),
	MS_Attacking		UMETA(DisplayName = "Attacking"),
};

.h

  • 添加球形组件,一个是表示检测角色的范围,一个是攻击敌人的范围
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	class USphereComponent* DetectSphere;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	class USphereComponent* AttackSphere;
  • 球形组件绑定的重叠函数
UFUNCTION()
	void OnDetectSphereOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, 
		UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

UFUNCTION()
	void OnDetectSphereOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
		UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

UFUNCTION()
	void OnAttackSphereOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, 
		UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

UFUNCTION()
	void OnAttackSphereOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
		UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
  • 声明AI控制器

class AAIController* _AIController;

  • 声明游戏状态
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	EMoveStatus MoveStatus;
  • 声明追击角色目标
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	class ARole* TargetRole;
  • 声明攻击角色目标
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	class ARole* HittingRole;
  • 声明移动到目标的函数
UFUNCTION(BlueprintCallable)
	void MoveToTarget();

.cpp文件

添加头文件:

#include "Components/SphereComponent.h"
#include "AIController.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Role.h"
  • 构造函数

加载球形组件和设置范围,初始化操作。

DetectSphere = CreateDefaultSubobject<USphereComponent>(TEXT("DetectSphere"));
DetectSphere->SetupAttachment(RootComponent);
DetectSphere->SetSphereRadius(300);

AttackSphere = CreateDefaultSubobject<USphereComponent>(TEXT("AttackSphere"));
AttackSphere->SetupAttachment(RootComponent);
AttackSphere->SetSphereRadius(100);
  • BeginPlay()

绑定重叠函数,这个算是重叠的基本操作了。

DetectSphere->OnComponentBeginOverlap.AddDynamic(this, &AEnemy::OnDetectSphereOverlapBegin);
DetectSphere->OnComponentEndOverlap.AddDynamic(this, &AEnemy::OnDetectSphereOverlapEnd);

AttackSphere->OnComponentBeginOverlap.AddDynamic(this, &AEnemy::OnAttackSphereOverlapBegin);
AttackSphere->OnComponentEndOverlap.AddDynamic(this, &AEnemy::OnAttackSphereOverlapEnd);

获得AI控制器:

_AIController = Cast<AAIController>(GetController());
  • OnDetectSphereOverlapBegin

触碰到检测球形组件的时候,设置我们的追击目标,然后移动到目标角色的位置。

  • OnDetectSphereOverlapEnd

检测球形组件重叠结束的时候,敌人不在进行追逐,目标角色置为空,AI控制器控制敌人停止移动,人物处于呆滞状态。

if (OtherActor) {
	ARole* _Role = Cast<ARole>(OtherActor);
	if (_Role == TargetRole) {
		TargetRole = nullptr;
		if (MoveStatus != EMoveStatus::MS_Attacking) {
			MoveStatus = EMoveStatus::MS_Idle;
		}

		if (_AIController) {
			_AIController->StopMovement();
		}
	}
}
  • OnAttackSphereOverlapBegin

在攻击范围之内的时候,敌人要进行攻击,设置攻击目标,敌人设置为攻击状态,如果敌人在移动状态就要停止移动。

if (!HittingRole) {
	if (OtherActor) {
		ARole* _Role = Cast<ARole>(OtherActor);
		if (_Role) {
			HittingRole = _Role;
			MoveStatus = EMoveStatus::MS_Attacking;
			if (_AIController) {
				_AIController->StopMovement();
			}
		}
	}
}
  • OnAttackSphereOverlapEnd

在攻击范围之外的时候,敌人就变成了追击状态,设置追击目标,攻击目标置为空。

if (OtherActor) {
	ARole* _Role = Cast<ARole>(OtherActor);
	if (_Role == HittingRole) {
		TargetRole = HittingRole;
		HittingRole = nullptr;
	}
}
  • MoveToTarget

让AI控制器控制敌人移动到角色的位置。

if (TargetRole) {
	if (_AIController) {
		FAIMoveRequest _MoveRequest;
		_MoveRequest.SetGoalActor(TargetRole);
		_MoveRequest.SetAcceptanceRadius(2);

		FNavPathSharedPtr NavPath;
		_AIController->MoveTo(_MoveRequest, &NavPath);
	}
}
else {
	MoveStatus = EMoveStatus::MS_Idle;
}

EnemyAnimInstance

创建继承AnimInstanceEnemyAnimInstance,这个就和之前的是一样的。

.h文件

初始化函数,更新函数,移动速度(便于我们区分人物状态)、敌人类、Pawn类。

virtual void NativeInitializeAnimation() override;

UFUNCTION(BlueprintCallable, Category = AnimationProperty)
	void UpdateAnimationProperties();

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Movement)
	float MovementSpeed;

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Movement)
	class AEnemy* _Enemy;

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Movement)
	class APawn* _Pawn;

.cpp文件

添加头文件:

#include "Enemy.h"
void UEnemyAnimInstance::NativeInitializeAnimation()
{
	if (!_Pawn) {
		_Pawn = TryGetPawnOwner();
	}
	_Enemy = Cast<AEnemy>(_Pawn);
}

void UEnemyAnimInstance::UpdateAnimationProperties()
{
	if (!_Pawn) {
		_Pawn = TryGetPawnOwner();
	}

	if (_Pawn) {
		FVector Speed = _Pawn->GetVelocity();
		FVector LateralSpeed = FVector(Speed.X, Speed.Y, 0);
		MovementSpeed = LateralSpeed.Size();
	}
}

蓝图操作

创建动画蓝图,
在这里插入图片描述
设置角色状态机:
在这里插入图片描述

在这里插入图片描述
攻击动画中要添加一个注意:
在这里插入图片描述

蓝图中要更新状态:
在这里插入图片描述
和人物是差不多的。

根据动作传来的提醒,我们要对敌人的状态进行设置:

在这里插入图片描述
最后将
在这里插入图片描述
添加到地图中,覆盖地面,按下P键之后就能看到绿色的区域(这个区域就是NPC移动的区域),如果有些区域不想要,就添加下面的修改区域,将区域变小。

  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在UE4中使用C++实现TexturerRenderTargetCube读取照片,你需要完成以下步骤: 1. 导入照片:在UE4编辑器中,右键单击Content Browser面板,选择Import选项,然后选择你想要导入的照片。 2. 创建TexturerRenderTargetCube:在你的UE4项目中,找到你想要添加TexturerRenderTargetCube的地方。然后在该位置创建一个TexturerRenderTargetCube对象。 3. 设置TexturerRenderTargetCube属性:在代码中设置你的TexturerRenderTargetCube对象的属性。为了从照片中创建立方体贴图,你需要设置RenderTarget的尺寸以及Texture的格式。 4. 从照片中创建立方体贴图:使用你导入的照片创建立方体贴图。你需要将照片分解为6个面,并将它们作为6个2D纹理分别应用到RenderTargetCube的6个面上。 5. 使用TexturerRenderTargetCube:将TexturerRenderTargetCube用于你的场景或材质中。你可以将它作为材质的纹理或将它用于场景中的天空盒。 下面是一些示例代码来实现这些步骤: ```cpp // 导入照片 UTexture2D* PhotoTexture = LoadObject<UTexture2D>(nullptr, TEXT("/Game/Textures/PhotoTexture.PhotoTexture")); // 创建TexturerRenderTargetCube UTextureRenderTargetCube* CubeRenderTarget = NewObject<UTextureRenderTargetCube>(); CubeRenderTarget->InitAutoFormat(256); // 设置TexturerRenderTargetCube属性 CubeRenderTarget->ClearColor = FLinearColor::Black; // 从照片中创建立方体贴图 int32 CubeFaceSize = CubeRenderTarget->SizeX / 4; for (int32 CubeFaceIndex = 0; CubeFaceIndex < 6; ++CubeFaceIndex) { // 创建一个2D纹理 UTexture2D* CubeFaceTexture = NewObject<UTexture2D>(); CubeFaceTexture->Source.Init(CubeFaceSize, CubeFaceSize, 1, 1, ETextureSourceFormat::TSF_BGRA8, &(PhotoTexture->PlatformData->Mips[0].BulkData)); // 应用2D纹理到RenderTargetCube CubeRenderTarget->GameThread_SetTextureCubeFace((ECubeFace)CubeFaceIndex, CubeFaceTexture, false, false); } // 使用TexturerRenderTargetCube UMaterialInstanceDynamic* DynamicMaterial = UMaterialInstanceDynamic::Create(Material, InWorld); DynamicMaterial->SetTextureParameterValue(TEXT("CubeTexture"), CubeRenderTarget); ``` 这样,你就可以使用C++实现TexturerRenderTargetCube读取照片了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值