【UE4】【C++】炮弹(子弹)使用方法(创建、作用力、范围伤害及接受伤害)
2018-03-14 14:37
1241 查看
创建:
首先,肯定需要一个C++类(Actor就可以)(我们就叫他Projectile--弹)
然后创建基于Projectile的蓝图类
一个炮弹需要什么:作为炮弹的物体、射出去的粒子效果、爆炸之后的粒子效果等等
h:#include "Components/StaticMeshComponent.h" //炮弹
#include "Particles/ParticleSystemComponent.h" //粒子效果
#include "GameFramework/ProjectileMovementComponent.h" //用于制作子弹炮弹的抛物线
cpp:AProjectile::AProjectile()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(FName("ProjectileMovement")); //生成组件
ProjectileMovementComponent->bAutoActivate = false; //自动飞行调成false
//炮弹
CollisionMesh = CreateDefaultSubobject<UStaticMeshComponent>(FName("CollisionMesh")); //创建CollisionMesh
SetRootComponent(CollisionMesh);//设置成根结点
CollisionMesh->SetNotifyRigidBodyCollision(true); //设置可以撞击到物体
CollisionMesh->SetVisibility(true); //设置可见
LaunchParticle = CreateDefaultSubobject<UParticleSystemComponent>(FName("LaunchParticle"));
LaunchParticle->AttachTo(RootComponent);//将粒子效果绑定在根结点上(即CollisionMesh)
LaunchParticle->SetAutoActivate(true); //不要创建好就启动
ImpactParticle = CreateDefaultSubobject<UParticleSystemComponent>(FName("ImpactParticle"));
ImpactParticle->AttachTo(RootComponent);
ImpactParticle->SetAutoActivate(false); //不要创建好就启动
}
// Called when the game starts or when spawned
void AProjectile::BeginPlay()
{
Super::BeginPlay();
CollisionMesh->OnComponentHit.AddDynamic(this, &AProjectile::OnHit); //将Projectile绑定在了物件上
}
// Called every frame
void AProjectile::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AProjectile::LaunchProjectile(float Speed) { //此函数用于鼠标左键输入连着的Fire函数(详情请见之前的生成子弹文章)
ProjectileMovementComponent->SetVelocityInLocalSpace(FVector::ForwardVector*Speed); //设置速度,因为是矢量所以乘向前的向量
ProjectileMovementComponent->Activate(); //可以飞行了
}
//碰撞后发生的事件
void AProjectile::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {
UE_LOG(LogTemp, Warning, TEXT("Hit")); //撞击后给个提示
ImpactParticle->Activate(true); //撞击后产生撞击后的粒子效果
CollisionMesh->SetNotifyRigidBodyCollision(false); //碰撞之后再也不发生碰撞事件
SetRootComponent(ImpactParticle);//删除了作为根结点的炮弹,所以要在删除前换一个根结点
CollisionMesh->DestroyComponent(); //不是DestroyActor,Component是单一一个
}之后在Projectile的蓝图中就可以看到
如果还有一个DefaultSceneRoot,只需保存重启之后便会消失
作用力:
在原有的Projectile的代码中添加
h:#include "PhysicsEngine/RadialForceComponent.h"
cpp:
在AProjectile中写:ExplosionForce= CreateDefaultSubobject<URadialForceComponent>(FName("ExplosionForce"));
ExplosionForce->AttachTo(RootComponent);
ExplosionForce->SetAutoActivate(false);在OnHit中写:ExplosionForce->FireImpulse(); //撞击后便释放力编译后在蓝图中可见:
多了一个ExplosionForce
之后便可在Details中设置他的各种东西啦!!
伤害值: http://api.unrealengine.com/INT/API/Runtime/Engine/Kismet/UGameplayStatics/ApplyRadialDamage/index.html
(
const UObject * WorldContextObject,
float BaseDamage,
const FVector & Origin,
float DamageRadius,
TSubclassOf < class UDamageType > DamageTypeClass,
const TArray < AActor * > & IgnoreActors,
AActor * DamageCauser,
AController * InstigatedByController,
bool bDoFullDamage,
ECollisionChannel DamagePreventionChannel
)
下面这个是在Radial范围内随中心递减伤害的方法 http://api.unrealengine.com/INT/API/Runtime/Engine/Kismet/UGameplayStatics/ApplyRadialDamageWithFalloff/index.html
(
const UObject * WorldContextObject,
float BaseDamage,
float MinimumDamage,
const FVector & Origin,
float DamageInnerRadius, //在几米以内都是最大伤害
float DamageOuterRadius, //在几米之外都是最小伤害
float DamageFalloff, //从里到外递减多少
TSubclassOf < class UDamageType > DamageTypeClass,
const TArray < AActor * > & IgnoreActors,
AActor * DamageCauser,
AController * InstigatedByController,
ECollisionChannel DamagePreventionChannel
)
Kismet/GameplayStatics.h
--------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------- http://api.unrealengine.com/INT/API/Runtime/Engine/GameFramework/AActor/TakeDamage/index.html
Syntaxvirtual float TakeDamage
(
float DamageAmount,
struct FDamageEvent const & DamageEvent,
AController * EventInstigator,
AActor * DamageCauser
)
h.(Projectile):UPROPERTY(EditAnywhere, Category = "Setup")
float ProjectileDamage = 20.0f;
cpp(Projectile):UGameplayStatics::ApplyRadialDamage(
this,
ProjectileDamage, //炮弹伤害 自己定义的
GetActorLocation(),
ExplosionForce->Radius, //爆炸范围作为伤害范围
UDamageType::StaticClass(), //需引用Engine/World.h 用于放更详细的伤害信息(比如是什么伤害:火焰、魔法……)
TArray<AActor*>() //传进一个Array数组不伤害(比如友军),没有友军传的是一个空数组
);这个时候Projectile就有伤害了 还要让被打的目标有生命值
被打的Actor(Tank):
h:(Tank)
重写virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;
int32 DamagePoint = FPlatformMath::RoundToInt(DamageAmount); //将伤害(float)通过四舍五入转为int,强制转型会向下取整
int32 DamageToApply = FMath::Clamp<int>(DamagePoint, 0, CurrentHp); //防止把血打到负数
CurrentHp -= DamageToApply;
if (CurrentHp <= 0) {
//Tank Dead
UE_LOG(LogTemp, Warning, TEXT("Tank Dead,Tank Name:%s"), *GetName());
}
return DamageToApply;
}
首先,肯定需要一个C++类(Actor就可以)(我们就叫他Projectile--弹)
然后创建基于Projectile的蓝图类
一个炮弹需要什么:作为炮弹的物体、射出去的粒子效果、爆炸之后的粒子效果等等
h:#include "Components/StaticMeshComponent.h" //炮弹
#include "Particles/ParticleSystemComponent.h" //粒子效果
#include "GameFramework/ProjectileMovementComponent.h" //用于制作子弹炮弹的抛物线
UProjectileMovementComponent *ProjectileMovementComponent = nullptr; UPROPERTY(VisibleAnywhere,Category="Components") UStaticMeshComponent* CollisionMesh = nullptr; UPROPERTY(VisibleAnywhere, Category = "Components") UParticleSystemComponent* LaunchParticle = nullptr; //烟雾 火 UPROPERTY(VisibleAnywhere, Category = "Components") UParticleSystemComponent* ImpactParticle = nullptr; //撞击 void LaunchProjectile(float Speed); //调用此函数时 设置速度 顺便让抛物线组件启用 UFUNCTION() //撞击事件 void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
cpp:AProjectile::AProjectile()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(FName("ProjectileMovement")); //生成组件
ProjectileMovementComponent->bAutoActivate = false; //自动飞行调成false
//炮弹
CollisionMesh = CreateDefaultSubobject<UStaticMeshComponent>(FName("CollisionMesh")); //创建CollisionMesh
SetRootComponent(CollisionMesh);//设置成根结点
CollisionMesh->SetNotifyRigidBodyCollision(true); //设置可以撞击到物体
CollisionMesh->SetVisibility(true); //设置可见
LaunchParticle = CreateDefaultSubobject<UParticleSystemComponent>(FName("LaunchParticle"));
LaunchParticle->AttachTo(RootComponent);//将粒子效果绑定在根结点上(即CollisionMesh)
LaunchParticle->SetAutoActivate(true); //不要创建好就启动
ImpactParticle = CreateDefaultSubobject<UParticleSystemComponent>(FName("ImpactParticle"));
ImpactParticle->AttachTo(RootComponent);
ImpactParticle->SetAutoActivate(false); //不要创建好就启动
}
// Called when the game starts or when spawned
void AProjectile::BeginPlay()
{
Super::BeginPlay();
CollisionMesh->OnComponentHit.AddDynamic(this, &AProjectile::OnHit); //将Projectile绑定在了物件上
}
// Called every frame
void AProjectile::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AProjectile::LaunchProjectile(float Speed) { //此函数用于鼠标左键输入连着的Fire函数(详情请见之前的生成子弹文章)
ProjectileMovementComponent->SetVelocityInLocalSpace(FVector::ForwardVector*Speed); //设置速度,因为是矢量所以乘向前的向量
ProjectileMovementComponent->Activate(); //可以飞行了
}
//碰撞后发生的事件
void AProjectile::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {
UE_LOG(LogTemp, Warning, TEXT("Hit")); //撞击后给个提示
ImpactParticle->Activate(true); //撞击后产生撞击后的粒子效果
CollisionMesh->SetNotifyRigidBodyCollision(false); //碰撞之后再也不发生碰撞事件
SetRootComponent(ImpactParticle);//删除了作为根结点的炮弹,所以要在删除前换一个根结点
CollisionMesh->DestroyComponent(); //不是DestroyActor,Component是单一一个
}之后在Projectile的蓝图中就可以看到
如果还有一个DefaultSceneRoot,只需保存重启之后便会消失
作用力:
在原有的Projectile的代码中添加
h:#include "PhysicsEngine/RadialForceComponent.h"
UPROPERTY(VisibleAnywhere, Category = "Components") URadialForceComponent* ExplosionForce = nullptr;
cpp:
在AProjectile中写:ExplosionForce= CreateDefaultSubobject<URadialForceComponent>(FName("ExplosionForce"));
ExplosionForce->AttachTo(RootComponent);
ExplosionForce->SetAutoActivate(false);在OnHit中写:ExplosionForce->FireImpulse(); //撞击后便释放力编译后在蓝图中可见:
多了一个ExplosionForce
之后便可在Details中设置他的各种东西啦!!
伤害值: http://api.unrealengine.com/INT/API/Runtime/Engine/Kismet/UGameplayStatics/ApplyRadialDamage/index.html
UGameplayStatics::ApplyRadialDamage
Choose your OS:Syntaxstatic bool ApplyRadialDamage(
const UObject * WorldContextObject,
float BaseDamage,
const FVector & Origin,
float DamageRadius,
TSubclassOf < class UDamageType > DamageTypeClass,
const TArray < AActor * > & IgnoreActors,
AActor * DamageCauser,
AController * InstigatedByController,
bool bDoFullDamage,
ECollisionChannel DamagePreventionChannel
)
下面这个是在Radial范围内随中心递减伤害的方法 http://api.unrealengine.com/INT/API/Runtime/Engine/Kismet/UGameplayStatics/ApplyRadialDamageWithFalloff/index.html
UGameplayStatics::ApplyRadialDamageWithFalloff
Choose your OS:Syntaxstatic bool ApplyRadialDamageWithFalloff(
const UObject * WorldContextObject,
float BaseDamage,
float MinimumDamage,
const FVector & Origin,
float DamageInnerRadius, //在几米以内都是最大伤害
float DamageOuterRadius, //在几米之外都是最小伤害
float DamageFalloff, //从里到外递减多少
TSubclassOf < class UDamageType > DamageTypeClass,
const TArray < AActor * > & IgnoreActors,
AActor * DamageCauser,
AController * InstigatedByController,
ECollisionChannel DamagePreventionChannel
)
Kismet/GameplayStatics.h
--------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------- http://api.unrealengine.com/INT/API/Runtime/Engine/GameFramework/AActor/TakeDamage/index.html
APawn::TakeDamage
Choose your OS:Override HierarchyAActor::TakeDamage()
|
(
float DamageAmount,
struct FDamageEvent const & DamageEvent,
AController * EventInstigator,
AActor * DamageCauser
)
h.(Projectile):UPROPERTY(EditAnywhere, Category = "Setup")
float ProjectileDamage = 20.0f;
cpp(Projectile):UGameplayStatics::ApplyRadialDamage(
this,
ProjectileDamage, //炮弹伤害 自己定义的
GetActorLocation(),
ExplosionForce->Radius, //爆炸范围作为伤害范围
UDamageType::StaticClass(), //需引用Engine/World.h 用于放更详细的伤害信息(比如是什么伤害:火焰、魔法……)
TArray<AActor*>() //传进一个Array数组不伤害(比如友军),没有友军传的是一个空数组
);这个时候Projectile就有伤害了 还要让被打的目标有生命值
被打的Actor(Tank):
h:(Tank)
重写virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;
private: UPROPERTY(EditAnywhere,Category="Health") int32 MaxHp = 100; //最大血量 UPROPERTY(VisibleAnywhere,Category="Health") int32 CurrentHp = MaxHp; //现在血量默认最大cpp:(Tank)float ATank::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) {
int32 DamagePoint = FPlatformMath::RoundToInt(DamageAmount); //将伤害(float)通过四舍五入转为int,强制转型会向下取整
int32 DamageToApply = FMath::Clamp<int>(DamagePoint, 0, CurrentHp); //防止把血打到负数
CurrentHp -= DamageToApply;
if (CurrentHp <= 0) {
//Tank Dead
UE_LOG(LogTemp, Warning, TEXT("Tank Dead,Tank Name:%s"), *GetName());
}
return DamageToApply;
}
相关文章推荐
- [UE4]注意事项,插件中蓝图方法库在C++中的使用
- 一个使用c++在lua中创建自定义数据类型的简易方法
- C++使用递归的方法创建二叉树
- C++进阶—>Win32 多线程的创建方法和基本使用
- 一个使用c++在lua中创建自定义数据类型的简易方法
- UE4使用C++创建枚举变量适用于C++与蓝图
- 【UE4】【C++】生成子弹、炮弹 (左键射出、抛物线)
- 在C++创建DLL,以及使用C++或者C#分别调用DLL中的方法
- UE4使用C++创建枚举变量适用于C++与蓝图
- C++创建dll文件及使用方法
- 使用C++创建蓝图公共静态方法
- 使用PHP 5.0创建图形的巧妙方法(一)
- 页面间传递变量的方法及使用范围的讨论
- 使用 PHP 5.0创建图形的巧妙方法(四)
- 使用 PHP 5.0创建图形的巧妙方法(二)
- C# 2.0:使用匿名方法、迭代程序和局部类来创建优雅的代码
- C++点滴:创建对象数组的时候,不要使用继承
- C# 2.0:使用匿名方法、迭代程序和局部类来创建优雅的代码
- 使用反射实现根据名称动态创建窗体的几种方法。
- 在C++中创建并使用Web服务