Ah, the main problem was that you were using UGameplayStatics::SpawnEmitterAtLocation, which only spawns the emitter and not a new paramcomponent.
To preserve the paramcomponent->emitter relationship, you need to make a new actor type with that hierarchy defined like so:
You’d probably want some code to auto-destroy the AMyProjectDemoHitEffect actor after a delay, too, but that should be fairly trivial…
#pragma once
#include "ParticleText/Public/ParticleTextParamComponent.h"
#include "MyProjectDemoOnHitActor.generated.h"
UCLASS()
class AMyProjectDemoOnHitActor : public AActor
{
GENERATED_BODY()
public:
AMyProjectDemoOnHitActor();
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = PrimaryStaticMesh, meta = (AllowPrivateAccess = "true"))
UStaticMeshComponent* StaticMesh;
UFUNCTION()
void OnHit(UPrimitiveComponent* ThisComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
};
UCLASS()
class AMyProjectDemoHitEffect : public AActor
{
GENERATED_BODY()
public:
AMyProjectDemoHitEffect();
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = ParticleText, meta = (AllowPrivateAccess = "true"))
UParticleTextParamComponent* DemoParticleTextParamComponent;
};
#include "MyProject.h"
#include "MyProjectDemoOnHitActor.h"
AMyProjectDemoOnHitActor::AMyProjectDemoOnHitActor()
{
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMesh->SetSimulatePhysics(true);
StaticMesh->SetEnableGravity(true);
StaticMesh->SetMassOverrideInKg(TEXT(""), 1000.f, true);
StaticMesh->bGenerateOverlapEvents = true;
StaticMesh->OnComponentHit.AddDynamic(this, &AMyProjectDemoOnHitActor::OnHit);
StaticMesh->BodyInstance.SetCollisionProfileName(TEXT("PhysicsActor"));
StaticMesh->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
}
void AMyProjectDemoOnHitActor::OnHit(UPrimitiveComponent* ThisComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
auto CurrentPlayer = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);
auto LookAtPlayerRotation = FRotationMatrix::MakeFromX(CurrentPlayer->GetActorLocation() - GetActorLocation()).Rotator();
AMyProjectDemoHitEffect* Effect = GetWorld()->SpawnActor<AMyProjectDemoHitEffect>(AMyProjectDemoHitEffect::StaticClass(), GetActorLocation(), LookAtPlayerRotation);
if (Effect != nullptr)
{
auto RandomText = FString::Printf(TEXT("Test %d"), FMath::RandRange(1, 4));
Effect->DemoParticleTextParamComponent->SetParamText(RandomText);
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor(168.f, 252.f, 0.f), FString::Printf(TEXT("OnHit(): SetParamText() to %s"), *RandomText));
}
}
AMyProjectDemoHitEffect::AMyProjectDemoHitEffect()
{
static ConstructorHelpers::FObjectFinder<UParticleSystem> DemoParticleComponentRef(TEXT("Demo'/Game/Demo/P_Demo.P_Demo'"));
UParticleSystemComponent* DemoParticleComponent = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("DemoParticleComponent"));
if (DemoParticleComponentRef.Succeeded())
{
DemoParticleComponent->SetTemplate(DemoParticleComponentRef.Object);
DemoParticleComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
}
DemoParticleTextParamComponent = CreateDefaultSubobject<UParticleTextParamComponent>(TEXT("DemoParticleTextParamComponent"));
DemoParticleTextParamComponent->AttachToComponent(DemoParticleComponent, FAttachmentTransformRules::KeepRelativeTransform);
}