Performance and Scaling

The plugin is built to hold 100,000+ live projectiles. Cost is kept bounded by budgets and two adaptive controllers, so frame time stays flat when the active count spikes.

Where the time goes

Stage Thread Bounded by
Flight integration Mass workers Linear in active count (very cheap)
Collision traces Mass workers Collision Budget Ms + trace budgets (adaptive)
Tracer gather + upload Game → render thread Max Tracers Drawn Per Frame (adaptive cull radius)
Impact bursts Game thread → GPU Max Impact Events Per Frame, cull distance
Smoke puffs Game thread → GPU Max Smoke Samples Per Frame, smoke cull distance
Decals Game thread Max Decals Per Frame, Max Live Decals
Audio Game thread Flyby / impact sounds per frame + minimum intervals

The two adaptive controllers

Both are on by default.

Collision (Collision Budget Ms, default 2 ms). When the measured collision pass exceeds the budget, trace budgets shrink and far projectiles trace less often (proj.FarTraceInterval stretches up to 16×). Their swept segments accumulate, so hits register a few frames later but nothing tunnels. Projectiles within proj.NearRadius (150 m) of the viewer keep a separate budget (proj.NearTraceBudget), so a distant swarm cannot starve the player's own shots.

Tracers (Max Tracers Drawn Per Frame, default 30,000). Every projectile simulates, but only the closest N are drawn. An adaptive cull radius converges on the budget, so game-thread copy, render upload and GPU spawn stay flat at 100k+ active.

Reading the numbers

proj.Stats prints a snapshot. Set Stats Log Interval (off by default) to get a periodic PERF line every that many seconds, category LogMassProjectiles. It reports:

PERF avg 118.4 FPS | active 20000 | drawn 20000 (cull 0 m) | traces/f 4096 (scale 1.00) | hits/f 312 | flybys total 12 | ... | sim 0.41 ms | collision 1.87 ms | push 0.62 ms | ...
Field Meaning
avg FPS Average frame rate over the log interval
active Live projectiles
drawn (cull) Tracers handed to the visualizer, and the adaptive tracer radius in metres (0 = unlimited)
traces/f (scale) Collision traces per frame, and the trace-budget scale (1 = full budgets; lower = collision ran over budget)
hits/f Hits per frame
flybys total Flyby sounds played this session
sim / collision / push ms Flight integration, collision, and gather/visualize time
damage sites / holes / meshcuts Used only by the optional Projectile Holes add-on (0 otherwise)

Use Unreal Insights (-trace=cpu,gpu) for a full profile. Mass processors show up as ProjectileSimProcessor, ProjectileCollisionProcessor and ProjectileVisualizationProcessor.

Tuning checklist

Symptom Try
CPU spikes during big volleys Lower Collision Budget Ms; lower proj.TraceBudget
Far hits register late Expected under load; raise Collision Budget Ms if you have headroom
GPU cost from tracers Lower Max Tracers Drawn Per Frame or set Tracer Cull Distance
Too much smoke overdraw Lower Max Smoke Samples Per Frame, Smoke Lifetime, or Smoke Cull Distance
Decal cost / scene proxies Lower Max Live Decals and Decal Lifetime
Physics cost from near misses Lower Max Proximity Impulse Queries, or proj.ProximityImpulse 0
Hitches on the first shot of a type Add the type to Replicated Types (preloaded at level load) or call Register Type Config at BeginPlay

Per-platform tuning

Put overrides in your project's Config/DefaultDeviceProfiles.ini:

[Android DeviceProfile]
+CVars=proj.CollisionBudgetMs=1.5
+CVars=proj.NearTraceBudget=1024
+CVars=proj.TraceBudget=512
+CVars=proj.FarTraceInterval=8
+CVars=proj.TracerBudget=8000
+CVars=proj.TracerCull=250000
+CVars=proj.SmokeBudget=256

[IOS DeviceProfile]
+CVars=proj.TracerBudget=8000
+CVars=proj.SmokeBudget=256

Watch the PERF line on the target device to see where the controllers settle.

Scalability

The plugin's Niagara components opt out of Niagara scalability culling (world-wide fixed bounds), because culling a shared system would hide every projectile at once. Control visual cost with the budgets above, and bind them to your scalability groups through device profiles or Scalability.ini CVars.

Need help? Contact support.