Blueprint and C++ API

Blueprint nodes

Mass Projectiles (function library)

Node Inputs → Output Description
Get Projectile Subsystem World Context → Projectile Subsystem The world's projectile subsystem (Game and PIE worlds).
Fire Projectiles World Context, Type Config, Fire Event → int Spawn Fire Event.Count projectiles of the type. Returns the number spawned. Registers the type on first use.
Clear Projectiles World Context Destroy every live projectile. Replicates when called on an authority server.
Is Gameplay Damage Impact Impact Type → bool True for Stop and Penetration Enter.

Projectile Subsystem

Node Inputs → Output Description
Spawn Projectiles Type Config, Fire Event → int Same as Fire Projectiles, called on the subsystem.
Register Type Config Type Config → int Preload a type and return its runtime index (-1 if it lacks Projectile Ballistics). Call at BeginPlay to avoid a first-shot hitch.
On Projectile Hit Event (event dispatcher) → Mass Projectile Hit Event Authority-only hits. Bind with Bind Event to On Projectile Hit Event.

Mass Projectile Fire (component)

Member Kind Description
Projectile Type Property (soft reference) Type asset to fire.
Rounds Per Minute Property Fire rate for Consume Fire Rounds (default 600).
Muzzle Offset Property Actor-space offset used by Fire (default 150, 0, 0).
Pellets Per Shot Property Projectiles per round (default 1).
Spread Half Angle Deg Property Random cone per projectile (default 0).
Fire (Rounds) Function From owner location + Muzzle Offset along the control rotation.
Fire From (Origin, Direction, Rounds) Function Explicit muzzle and direction.
Consume Fire Rounds (Delta Seconds, Max Rounds This Frame = 32) → int Function Whole rounds owed this frame at Rounds Per Minute.
Reset Fire Accumulator Function Restart the fire-rate accumulator (call on trigger press).

Mass Projectile Hit (component)

Member Kind Description
Owner Hits Only Property Forward only hits whose Hit Actor is this component's owner.
On Projectile Hit (Hit) Event dispatcher Authority-only hit events.

Structs and enums

Projectile Fire Event (FProjectileFireEvent)

Field Type Default Description
Origin Vector 0 World spawn point
Direction Vector +X Fire direction (normalized internally)
Count int 1 Projectiles in this volley
Speed float 0 Launch speed (cm/s); ≤ 0 = type's Default Speed
Spread Half Angle Deg float 0 Random cone per projectile
Random Seed int 0 Deterministic spread/speed seed; 0 = automatic

Mass Projectile Hit Event (FMassProjectileHitEvent)

See the field table in Hits and Damage.

Projectile Impact Type (EProjectileImpactType)

Stop · Ricochet · Penetration Enter · Penetration Exit

C++

Add the module to your Build.cs:

PublicDependencyModuleNames.AddRange(new string[] { "MassProjectileSubsystem", "MassSpawner" });

(MassSpawner provides UMassEntityConfigAsset.)

Firing

#include "Projectile/ProjectileSubsystem.h"
#include "MassEntityConfigAsset.h"

void AMyTurret::FireVolley(const UMassEntityConfigAsset* Type)
{
    UProjectileSubsystem* Projectiles = GetWorld()->GetSubsystem<UProjectileSubsystem>();
    if (!Projectiles) return;

    FProjectileFireEvent Event;
    Event.Origin = Muzzle->GetComponentLocation();
    Event.Direction = Muzzle->GetForwardVector();
    Event.Count = 12;
    Event.SpreadHalfAngleDeg = 2.f;

    Projectiles->SpawnProjectiles(Type, Event);   // replicates automatically on an authority
}

Native hit listener

OnProjectileHit is a native multicast delegate with the compact worker payload (FProjectileHitPayload). It is authority-only, like the Blueprint event.

void UMyDamageSystem::Initialize(FSubsystemCollectionBase& Collection)
{
    Super::Initialize(Collection);
    if (UProjectileSubsystem* Projectiles = Collection.InitializeDependency<UProjectileSubsystem>())
    {
        HitHandle = Projectiles->OnProjectileHit.AddUObject(this, &UMyDamageSystem::HandleHit);
    }
}

void UMyDamageSystem::HandleHit(const FProjectileHitPayload& Hit)
{
    if (Hit.Event == EProjectileImpactType::Stop || Hit.Event == EProjectileImpactType::PenetrationEnter)
    {
        // Hit.HitActor, Hit.Location, Hit.Surface, Hit.TypeIndex ...
    }
}

OnProjectileHitEvent (dynamic, FMassProjectileHitEvent) carries the same hits with Damage and Type Config resolved. Prefer it when you want Base Damage.

OnProjectileHitLocal has the same signature but fires on every machine, clients included, each with its own locally simulated copy of the hit. Use it for cosmetic reactions only (hit markers, UI, local effects), never for damage or scoring.

Useful subsystem calls

Function Description
SpawnProjectiles(TypeConfig, FireEvent) Spawn; returns the count spawned
RegisterTypeConfig(TypeConfig) Preload a type; returns its runtime index
RequestClearAll() Clear all projectiles (replicates from an authority)
GetStats() FStats snapshot: Active, Traces, Hits, TracersDrawn, timings
SetWindVelocity(FVector) / GetWindVelocity() Manual wind (cm/s)
SetVisualizer(IProjectileVisualizer*) Replace the renderer (see below)

Custom visualizer (C++)

The core module has no Niagara dependency. To draw projectiles another way (instanced meshes, a custom Niagara layout, a debug renderer):

  1. Implement IProjectileVisualizer (Projectile/ProjectileVisualizer.h):
Method Called
Prewarm() World init, BeginPlay, and each cosmetic frame (idempotent)
ResetAssetCache() proj.ReloadAssets
CanDrawImpacts() Return false to use the cheap per-type fallback puff
DrawImpacts(TConstArrayView<FProjectileImpactFXEvent>) Every cosmetic frame, even when empty
DrawTracers(TypeIndex, const FProjectileTypeViz&) Per type, each frame (Positions / Velocities within the tracer budget)
DrawSmoke(TConstArrayView<FProjectileSmokeSample>) Every cosmetic frame, even when empty
  1. Register it from a UWorldSubsystem::Initialize (before world PostInitialize):
Collection.InitializeDependency<UProjectileSubsystem>()->SetVisualizer(&MyVisualizer);
  1. Turn off Project Settings → Mass Projectile Niagara → Enable Niagara Visualizer.

All visualizer methods run on the game thread, and only where a local viewer exists (never on dedicated servers).

Need help? Contact support.