C++代码实现OnComponentHit事件粒子消失蓝图--斯坦福

发布时间 2023-10-21 10:24:51作者: XTG111

image

蓝图节点

OnComponentBeginOverlap,OnComponentHit等等之类如何迁移到C++中

方法

这些蓝图节点实际上就是一个UE4已经定义好的事件,在蓝图中使用模块的连接来实现事件的触发后续操作。在C++中通过AddDynamic(),进行函数绑定,实现蓝图中的模块操作
动态委托

操作

可以从蓝图中看到OnCompponent*事件是需要绑定在一个Component的,所以对于事件的操作需要在构造函数中进行

SphereComp->OnComponentHit.AddDynamic(this,&ClassName::Func)

而最需要注意的是,对于不同的OnComponent事件,Func的参数是需要调整的,否则会报错,具体的方法可以从源码中获得参数
image

DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams( FComponentHitSignature, UPrimitiveComponent, OnComponentHit, UPrimitiveComponent*, HitComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, FVector, NormalImpulse, const FHitResult&, Hit );

接下来就是定义函数,将蓝图中后续的操作编写到函数中。
其中蓝图对销毁粒子时增加了一个粒子特效,利用SpawnEmitterAtLocation,获取接触位置,然后导入粒子特效,接着Destroy。
SpawnEmitterAtLocation是在GameplayStatics类中定义的方法,需要#include "Kismet\GameplayStatics.h"

void ATMagicProjectile::OnActorHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector Normallpulse, const FHitResult& SweepResult)
{
	FVector Loc = this->GetActorLocation();
	FRotator Rot = this->GetActorRotation();

	if (OtherActor && OtherActor != GetInstigator()) {
		UGameplayStatics::SpawnEmitterAtLocation(this->EffectComp, HitFX, Loc, Rot);
		Destroy();
	}
}

HitFX为粒子效果,使用FObjectFinder进行资源的加载,但我的操作提示CDO Failue,没法正常加载资源┭┮﹏┭┮。
参考

完整代码
.h文件

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TMagicProjectile.generated.h"

class USphereComponent;
class UProjectileMovementComponent;
class UParticleSystem;

UCLASS()
class PHONETEST1_API ATMagicProjectile : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATMagicProjectile();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	//球体体积,粒子的模型放置
	UPROPERTY(VisibleAnywhere)
		USphereComponent* SphereComp;

	//抛体运动组件
	UPROPERTY(VisibleAnywhere)
		UProjectileMovementComponent* MovementComp;

	//粒子的状态,后续可以集合在粒子组件中
	UPROPERTY(VisibleAnywhere)
		UParticleSystemComponent* EffectComp;

	//添加粒子效果
	UPROPERTY(EditDefaultsOnly)
		UParticleSystem* HitFX;

	//粒子碰撞后销毁
	UFUNCTION()
		void OnActorHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector Normallpulse, const FHitResult& SweepResult);


public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
};

.cpp文件

// Fill out your copyright notice in the Description page of Project Settings.


#include "TMagicProjectile.h"
#include "Components\SphereComponent.h"
#include "Particles\ParticleSystemComponent.h"
#include "GameFramework\ProjectileMovementComponent.h"
#include "TCharacterComponent.h"
#include "Kismet\GameplayStatics.h"

// Sets default values
ATMagicProjectile::ATMagicProjectile()
{
 	// 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;

	SphereComp = CreateDefaultSubobject<USphereComponent>("SphereComp");
	RootComponent = SphereComp;

	SphereComp->SetCollisionProfileName("Projectile");

	EffectComp = CreateDefaultSubobject<UParticleSystemComponent>("EffectComp");
	EffectComp->SetupAttachment(SphereComp);

	MovementComp = CreateDefaultSubobject<UProjectileMovementComponent>("MovementComp");
	MovementComp->InitialSpeed = 1000.0f;
	MovementComp->bRotationFollowsVelocity = true;
	MovementComp->bInitialVelocityInLocalSpace = true;
	
	SphereComp->OnComponentHit.AddDynamic(this, &ATMagicProjectile::OnActorHit);

	static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleAsset(TEXT("/Content/StarterContent/Particles/P_Fire.P_Fire_C"));
	if (ParticleAsset.Succeeded())
	{
		HitFX = ParticleAsset.Object;
	}
}

// Called when the game starts or when spawned
void ATMagicProjectile::BeginPlay()
{
	Super::BeginPlay();
	ObjToSpawn.Broadcast();
	
}

void ATMagicProjectile::OnActorHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector Normallpulse, const FHitResult& SweepResult)
{
	FVector Loc = this->GetActorLocation();
	FRotator Rot = this->GetActorRotation();

	if (OtherActor && OtherActor != GetInstigator()) {
		UGameplayStatics::SpawnEmitterAtLocation(this->EffectComp, HitFX, Loc, Rot);
		Destroy();
	}
}

// Called every frame
void ATMagicProjectile::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}