当前位置:   article > 正文

斯坦福UE4 + C++课程学习记录 20:位移技能_斯坦福 c++ 传送

斯坦福 c++ 传送

目录

1. 创建粒子类

2. 实现传送

3. 动画设置


        这节将会完成课程设置的第二次作业之一 —— 实现角色的粒子位移技能,即发射出一个特殊的粒子,经过一定时间后,该粒子会爆炸并将角色传送到爆炸位置。

1. 创建粒子类

        考虑到后面制作的粒子都需要实现爆炸效果,所以在SurProjectileBase中添加实现爆炸的函数和OnActorHit事件函数,爆炸函数仅包括最基本的爆炸后销毁自身的功能,方便子类可以根据自己的需求来进行重写。绑定事件的方法已经在第6、12节的爆炸桶内容出现过,重写函数的内容已经在第7节打开宝箱的文章中出现过。

  1. // SurProjectileBase.h
  2. UPROPERTY(EditDefaultsOnly, Category = "Effects")
  3. UParticleSystem* ImpactVFX;//VFX指Visual effects, 即视觉特效,负责爆炸时的特效
  4. UFUNCTION()
  5. virtual void OnActorHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
  6. UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
  7. void Explode(); // 爆炸函数
  8. // SurProjectileBase.cpp
  9. void ASurProjectileBase::OnActorHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
  10. {
  11. Explode();
  12. }
  13. // BlueprintNativeEvent需要加上后缀_Implementation
  14. void ASurProjectileBase::Explode_Implementation()
  15. {
  16. // IsPendingKill确保对象有效,防止重复destroy
  17. if (ensure(IsPendingKill()))
  18. {
  19. // 触发爆炸时的特效,特效样式在UE中设置ImpactVFX变量
  20. UGameplayStatics::SpawnEmitterAtLocation(this, ImpactVFX, GetActorLocation(), GetActorRotation());
  21. Destroy();
  22. }
  23. }

        由于这个技能需要实现额外的传送角色代码,因此我们要在UE中创建一个新的粒子类SurDashProjectile,在创建时选择“显示所有类”,并通过搜索选择,从上一节创建的基类SurProjectileBase派生出来。

        课程中在DashProjectile中设置两个时间,经过DetonateDelay后生成爆炸特效,然后再经过TeleportDelay后传送角色。将控制爆炸的TimerHandle_DelayedDetonate声明为类的保护成员,当粒子提前遇到障碍物爆炸调用Explode函数时,我们可以手动清除这个Timer,从而防止触发两次。相对的,控制传送延迟的Timer不涉及这个问题,因此定义为局部变量即可:

  1. #pragma once
  2. #include "CoreMinimal.h"
  3. #include "SurProjectileBase.h"
  4. #include "SurDashProjectile.generated.h"
  5. UCLASS()
  6. class SURKEAUE_API ASurDashProjectile : public ASurProjectileBase
  7. {
  8. GENERATED_BODY()
  9. public:
  10. ASurDashProjectile();
  11. protected:
  12. UPROPERTY(EditDefaultsOnly, Category = "Teleport")
  13. float TeleportDelay; // 传送延迟
  14. UPROPERTY(EditDefaultsOnly, Category = "Teleport")
  15. float DetonateDelay; // 爆炸延迟
  16. // hit后清除计时器
  17. FTimerHandle TimerHandle_DelayedDetonate;
  18. virtual void Explode_Implementation() override;
  19. void TeleportInstigator();
  20. virtual void BeginPlay() override;
  21. };

2. 实现传送

        实现角色的传送,可以直接使用UE的TeleportTo函数接口。这部分需要注意的是,一进入Explode就要清除控制爆炸的Timer,防止提前触发Hit事件爆炸后、原有的计时器结束再次触发。

  1. #include "SurDashProjectile.h"
  2. #include "Kismet/GameplayStatics.h"
  3. #include "Particles/ParticleSystemComponent.h"
  4. #include "GameFramework/ProjectileMovementComponent.h"
  5. ASurDashProjectile::ASurDashProjectile()
  6. {
  7. TeleportDelay = 0.2f;
  8. DetonateDelay = 0.2f;
  9. MoveComp->InitialSpeed = 6000.f;
  10. }
  11. void ASurDashProjectile::BeginPlay()
  12. {
  13. Super::BeginPlay();
  14. // 到爆炸时间后,触发Explode()
  15. GetWorldTimerManager().SetTimer(TimerHandle_DelayedDetonate, this, &ASurDashProjectile::Explode, DetonateDelay);
  16. }
  17. void ASurDashProjectile::Explode_Implementation()
  18. {
  19. // 可能有碰到障碍物提前爆炸的情况,因此要清除Timer防止被调用两次
  20. GetWorldTimerManager().ClearTimer(TimerHandle_DelayedDetonate);
  21. // 爆炸特效
  22. UGameplayStatics::SpawnEmitterAtLocation(this, ImpactVFX, GetActorLocation(), GetActorRotation());
  23. // 粒子爆炸后关闭系统、停止移动、停止碰撞
  24. EffectComp->DeactivateSystem();
  25. MoveComp->StopMovementImmediately();
  26. SetActorEnableCollision(false);
  27. // 到传送时间后,触发传送
  28. FTimerHandle TimerHandle_DelayedTeleport;
  29. GetWorldTimerManager().SetTimer(TimerHandle_DelayedTeleport, this, &ASurDashProjectile::TeleportInstigator, TeleportDelay);
  30. // 不调用base中的Explode中的destroy自身,因为传送时间计时器需要一点时间
  31. //Super::Explode_Implementation();
  32. }
  33. void ASurDashProjectile::TeleportInstigator()
  34. {
  35. AActor* ActorToTeleport = GetInstigator();
  36. if (ensure(ActorToTeleport))
  37. {
  38. // 传送时保持角色原始Rotation
  39. ActorToTeleport->TeleportTo(GetActorLocation(), ActorToTeleport->GetActorRotation(), false, false);
  40. }
  41. // 之前没有调用,现在销毁
  42. Destroy();
  43. }

        接下来就是常规的绑定按键操作,在UE中创建蓝图类,然后设置发射的粒子为该蓝图类,这已经在之前的内容出现过很多次,故不再赘述。


3. 动画设置

        最后,在创建的蓝图类中设置粒子的动画。一共需要设置两个动画:一是发射出去粒子的样子,对应ProjectileBase中的Effect Comp;二是爆炸时的动画,对应刚刚声明的ImpactVFX。

        我设置的特效分别为P_Gideon_Burden_Projectile和P_Gideon_Burden_DoT2_End,注意ImpactVFX要设置名字带有End或Destroy等会自动结束的动画,否则爆炸后的粒子会一直停留在世界中,大家可以根据喜好任意选择粒子特效。

图20-1 运行测试

        在C++中我们将两个延迟使用UPROPERTY暴露到了UE中,所以此时可以很方便地调节数据。我将爆炸延迟设置为1,传送延迟设置为0.2,即正常情况下粒子飞行1s后再经过0.2s,角色会传送到粒子最终位置。但如果粒子遇到障碍物,则代码中清除Timer的语句就会发挥作用,在0.2s后直接传送角色,效果如下:

图20-2 提前Explode

        最后我想说的是,课程的作业部分由于没有足够的指引,复现的难度确实比课程内容更大,但同时也给了我很多迫使自己摸索解决问题的机会。所以也十分建议大家可以先自行探索尝试实现作业内容,这对加深对UE的理解十分有用。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/611706
推荐阅读
相关标签
  

闽ICP备14008679号