UE4 C++设置攻击间隔面向敌人攻击
Posted TanZq_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4 C++设置攻击间隔面向敌人攻击相关的知识,希望对你有一定的参考价值。
效果展示
当人物背对着敌人的时候,他会回头攻击敌人。
敌人会等待一段时间之后再攻击,这个图片无法展示就不展示啦。
C++ 代码实现
Role 第三人称角色类
.h
// 设置当前要攻击的目标
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
class AEnemy* TargetEnemy;
// 球形碰撞组件,主要作用就是检测敌人于它重叠与否。
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
class USphereComponent* DetectSphere;
// 球形组件绑定的函数
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);
.cpp
- 构造函数
// 初始化球形组件,附加在根组件上
DetectSphere = CreateDefaultSubobject<USphereComponent>(TEXT("DetectSphere"));
DetectSphere->SetupAttachment(RootComponent);
- BeginPlay
// 绑定重叠发生反应的函数
DetectSphere->OnComponentBeginOverlap.AddDynamic(this, &ARole::OnDetectSphereOverlapBegin);
DetectSphere->OnComponentEndOverlap.AddDynamic(this, &ARole::OnDetectSphereOverlapEnd);
// 先把所有反应通道忽略,然后再打开对Pawn类的通道。
DetectSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
DetectSphere->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Overlap);
- OnDetectSphereOverlapBegin
// 重叠开始函数的作用就是将目标保存一下
if (!TargetEnemy) {
if (OtherActor) {
AEnemy* Enemy = Cast<AEnemy>(OtherActor);
if (Enemy) {
TargetEnemy = Enemy;
}
}
}
- OnDetectSphereOverlapEnd
// 离开的时候就将攻击目标设置为空。
if (OtherActor) {
AEnemy* Enemy = Cast<AEnemy>(OtherActor);
if (Enemy == TargetEnemy) {
TargetEnemy = nullptr;
}
}
- AttackBegin
// 如果有攻击目标
if (TargetEnemy) {
FRotator CurrentRotation = GetActorRotation();
// 通过FindLookAtRotation函数或得当前目标到攻击目标的Z轴
FRotator TargetRotation = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), TargetEnemy->GetActorLocation());
// 将人物的Z轴修改一下就可以了
TargetRotation = FRotator(CurrentRotation.Pitch, TargetRotation.Yaw, CurrentRotation.Roll);
SetActorRotation(TargetRotation);
}
Z轴是这个蓝色的,所以只需要修改Z轴即可。
这个情况是对应于有重力的情况,如果是其他的状态就要经过一番计算了。
修改一下这个检测球的范围,面向敌人功能完成。
Enemy
.h
// 冷却时间,记得在编辑器中赋值,默认为 0s
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float AttackInterval;
// 是否在冷却时间内
bool bInColdTime;
// 储存时间的变量
FTimerHandle AttackTimer;
// 攻击时间截止
void OnAttackTimeOut();
// 更新状态。
void UpdateStatus();
.cpp
- UpdateStatus
// 更新状态
if (HittingRole) {
// 有攻击角色移动到攻击角色
MoveToTarget();
// 只有不在冷却时间之内才可以进行攻击
if (!bInColdTime) {
AttackBegin();
}
}
else if (TargetRole) {
// 非攻击状态,才可以进行移动
if (!Attacking) {
MoveStatus = EMoveStatus::MS_MoveToTarget;
}
MoveToTarget();
}
else {
MoveStatus = EMoveStatus::MS_Idle;
}
- OnAttackSphereOverlapBegin
if (!HittingRole) {
if (OtherActor) {
ARole* _Role = Cast<ARole>(OtherActor);
if (_Role) {
HittingRole = _Role;
MoveStatus = EMoveStatus::MS_Attacking;
// 只有不在冷却时间才可以进行攻击
if (!bInColdTime) {
AttackBegin();
}
if (_AIController) {
_AIController->StopMovement();
}
}
}
}
- OnAttackSphereOverlapEnd
if (OtherActor) {
ARole* _Role = Cast<ARole>(OtherActor);
if (_Role && _Role == HittingRole) {
TargetRole = HittingRole;
HittingRole = nullptr;
// 离开攻击范围之后,要对状态进行更新
UpdateStatus();
}
}
- AttackBegin
void AEnemy::AttackBegin()
{
if (!HittingRole) return;
UAnimInstance* Instance = GetMesh()->GetAnimInstance();
if (_AnimMontage && Instance && !Instance->Montage_IsPlaying(_AnimMontage)) {
// 和角色一样,面向敌人
if (HittingRole && !Attacking) {
FRotator CurrentRotation = GetActorRotation();
FRotator TargetRotation = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), HittingRole->GetActorLocation());
TargetRotation = FRotator(CurrentRotation.Pitch, TargetRotation.Yaw, CurrentRotation.Roll);
SetActorRotation(TargetRotation);
}
Attacking = true;
// 攻击开始的时候,要设置为冷却时间,清空之前的时间,重新计时。
bInColdTime = true;
GetWorldTimerManager().ClearTimer(AttackTimer);
GetWorldTimerManager().SetTimer(AttackTimer, this, &AEnemy::OnAttackTimeOut, AttackInterval);
Instance->Montage_Play(_AnimMontage);
Instance->Montage_JumpToSection(FName("Attack01"), _AnimMontage);
if (AttackSound) {
UGameplayStatics::PlaySound2D(this, AttackSound);
}
}
}
- AttackEnd
void AEnemy::AttackEnd()
{
Attacking = false;
// 攻击结束之后也要更新状态
UpdateStatus();
}
其实就是攻击前加个时间判断,其他都差不多,时间的管理就交给FTimerHandle。到点就更新CD状态。
结束!编译试试吧!
以上是关于UE4 C++设置攻击间隔面向敌人攻击的主要内容,如果未能解决你的问题,请参考以下文章