赞
踩
目录
这节将会完成课程设置的第二次作业之一 —— 实现角色的粒子位移技能,即发射出一个特殊的粒子,经过一定时间后,该粒子会爆炸并将角色传送到爆炸位置。
考虑到后面制作的粒子都需要实现爆炸效果,所以在SurProjectileBase中添加实现爆炸的函数和OnActorHit事件函数,爆炸函数仅包括最基本的爆炸后销毁自身的功能,方便子类可以根据自己的需求来进行重写。绑定事件的方法已经在第6、12节的爆炸桶内容出现过,重写函数的内容已经在第7节打开宝箱的文章中出现过。
- // SurProjectileBase.h
-
- UPROPERTY(EditDefaultsOnly, Category = "Effects")
- UParticleSystem* ImpactVFX;//VFX指Visual effects, 即视觉特效,负责爆炸时的特效
-
- UFUNCTION()
- virtual void OnActorHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
-
- UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
- void Explode(); // 爆炸函数
-
-
- // SurProjectileBase.cpp
-
- void ASurProjectileBase::OnActorHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
- {
- Explode();
- }
-
- // BlueprintNativeEvent需要加上后缀_Implementation
- void ASurProjectileBase::Explode_Implementation()
- {
- // IsPendingKill确保对象有效,防止重复destroy
- if (ensure(IsPendingKill()))
- {
- // 触发爆炸时的特效,特效样式在UE中设置ImpactVFX变量
- UGameplayStatics::SpawnEmitterAtLocation(this, ImpactVFX, GetActorLocation(), GetActorRotation());
-
- Destroy();
- }
- }
由于这个技能需要实现额外的传送角色代码,因此我们要在UE中创建一个新的粒子类SurDashProjectile,在创建时选择“显示所有类”,并通过搜索选择,从上一节创建的基类SurProjectileBase派生出来。
课程中在DashProjectile中设置两个时间,经过DetonateDelay后生成爆炸特效,然后再经过TeleportDelay后传送角色。将控制爆炸的TimerHandle_DelayedDetonate声明为类的保护成员,当粒子提前遇到障碍物爆炸调用Explode函数时,我们可以手动清除这个Timer,从而防止触发两次。相对的,控制传送延迟的Timer不涉及这个问题,因此定义为局部变量即可:
- #pragma once
-
- #include "CoreMinimal.h"
- #include "SurProjectileBase.h"
- #include "SurDashProjectile.generated.h"
-
-
- UCLASS()
- class SURKEAUE_API ASurDashProjectile : public ASurProjectileBase
- {
- GENERATED_BODY()
-
- public:
-
- ASurDashProjectile();
-
- protected:
-
- UPROPERTY(EditDefaultsOnly, Category = "Teleport")
- float TeleportDelay; // 传送延迟
-
- UPROPERTY(EditDefaultsOnly, Category = "Teleport")
- float DetonateDelay; // 爆炸延迟
-
- // hit后清除计时器
- FTimerHandle TimerHandle_DelayedDetonate;
-
- virtual void Explode_Implementation() override;
-
- void TeleportInstigator();
-
- virtual void BeginPlay() override;
-
- };
实现角色的传送,可以直接使用UE的TeleportTo函数接口。这部分需要注意的是,一进入Explode就要清除控制爆炸的Timer,防止提前触发Hit事件爆炸后、原有的计时器结束再次触发。
- #include "SurDashProjectile.h"
- #include "Kismet/GameplayStatics.h"
- #include "Particles/ParticleSystemComponent.h"
- #include "GameFramework/ProjectileMovementComponent.h"
-
-
- ASurDashProjectile::ASurDashProjectile()
- {
- TeleportDelay = 0.2f;
- DetonateDelay = 0.2f;
-
- MoveComp->InitialSpeed = 6000.f;
- }
-
- void ASurDashProjectile::BeginPlay()
- {
- Super::BeginPlay();
-
- // 到爆炸时间后,触发Explode()
- GetWorldTimerManager().SetTimer(TimerHandle_DelayedDetonate, this, &ASurDashProjectile::Explode, DetonateDelay);
- }
-
- void ASurDashProjectile::Explode_Implementation()
- {
- // 可能有碰到障碍物提前爆炸的情况,因此要清除Timer防止被调用两次
- GetWorldTimerManager().ClearTimer(TimerHandle_DelayedDetonate);
- // 爆炸特效
- UGameplayStatics::SpawnEmitterAtLocation(this, ImpactVFX, GetActorLocation(), GetActorRotation());
-
- // 粒子爆炸后关闭系统、停止移动、停止碰撞
- EffectComp->DeactivateSystem();
- MoveComp->StopMovementImmediately();
- SetActorEnableCollision(false);
-
- // 到传送时间后,触发传送
- FTimerHandle TimerHandle_DelayedTeleport;
- GetWorldTimerManager().SetTimer(TimerHandle_DelayedTeleport, this, &ASurDashProjectile::TeleportInstigator, TeleportDelay);
-
- // 不调用base中的Explode中的destroy自身,因为传送时间计时器需要一点时间
- //Super::Explode_Implementation();
- }
-
- void ASurDashProjectile::TeleportInstigator()
- {
- AActor* ActorToTeleport = GetInstigator();
- if (ensure(ActorToTeleport))
- {
- // 传送时保持角色原始Rotation
- ActorToTeleport->TeleportTo(GetActorLocation(), ActorToTeleport->GetActorRotation(), false, false);
- }
- // 之前没有调用,现在销毁
- Destroy();
- }
接下来就是常规的绑定按键操作,在UE中创建蓝图类,然后设置发射的粒子为该蓝图类,这已经在之前的内容出现过很多次,故不再赘述。
最后,在创建的蓝图类中设置粒子的动画。一共需要设置两个动画:一是发射出去粒子的样子,对应ProjectileBase中的Effect Comp;二是爆炸时的动画,对应刚刚声明的ImpactVFX。
我设置的特效分别为P_Gideon_Burden_Projectile和P_Gideon_Burden_DoT2_End,注意ImpactVFX要设置名字带有End或Destroy等会自动结束的动画,否则爆炸后的粒子会一直停留在世界中,大家可以根据喜好任意选择粒子特效。
在C++中我们将两个延迟使用UPROPERTY暴露到了UE中,所以此时可以很方便地调节数据。我将爆炸延迟设置为1,传送延迟设置为0.2,即正常情况下粒子飞行1s后再经过0.2s,角色会传送到粒子最终位置。但如果粒子遇到障碍物,则代码中清除Timer的语句就会发挥作用,在0.2s后直接传送角色,效果如下:
最后我想说的是,课程的作业部分由于没有足够的指引,复现的难度确实比课程内容更大,但同时也给了我很多迫使自己摸索解决问题的机会。所以也十分建议大家可以先自行探索尝试实现作业内容,这对加深对UE的理解十分有用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。