Optimizing Projectiles Movement

Hello everyone, I am currently facing a problem and could really use some help.

I have implemented an automatic gun in the Unreal Engine that spawns projectile actors. These projectiles can vary, ranging from simple bullets to homing missiles or projectiles affected by gravity. However, I am experiencing significant performance issues when I have around 500 projectiles spawned from the gun, causing the FPS to drop to around 20.

The projectile actors have a hierarchy consisting of

  • Static Mesh Component

->Niagara Trail

→ Radial Force Component

  • Projectile Movement Component.

To segregate the issue, I have tried removing the mesh component and clearing the Niagara Trail Component. After disabling the tick on the projectile movement component the performance improves.

After researching on the Unreal Engine forums and Reddit, I have come across a few potential solutions, but none seem to fully address my requirements:

1. Line Trace: This may work for projectiles that don’t consider gravity or homing functionality, but it may not be suitable for my case.

2. Niagara Particles: How to pass data between C++ and Niagara Particles. Also Found Niagara Collision to Apply Gameplay Effect? - #9 by Michael.Galetzka which tells to avoid using Niagara Particles.

3. Bullet Manager: Implementing a manager to handle projectile movement with a single tick could be a viable solution, but it may not work well for projectiles with gravity or homing capabilities.

I have also implemented object pooling, which has helped in reducing time that was spent on actor creation and destruction, but it does not have any effect on the active projectiles in the level.

Given my requirements:

  1. I need to handle up to 2000 projectiles.

  2. The projectiles can be homing missiles, affected by gravity, or simple bullets, and they all need to hit their targets.

This is part of my upcoming Turret Plugin, and as a plugin, I cannot predict the specific usage scenarios. It may be used in large or small levels. For larger levels, I could potentially reduce the tick rate based on the distance from the player.

If anyone has any suggestions or alternative solutions to address this issue, I would greatly appreciate your help. I have been stuck on this problem for a while and any assistance would be immensely valuable. Thank you!"

1 Like

Forgot to mention, the plugin is designed specifically for single player games.

Also, Disabling Collision improves performance. So I guess there are two things that are affecting performance.

  1. Collision on static mesh.

  2. Projectile movement tick

Bump!

If you need to scale things into the thousands, I’d recommend to avoid any architecture where things tick individually (e.g. having a component per bullet). Either check out how to leverage the Mass framework and drive all behavior from there. Or if you want to handle everything yourself in C++, create a subsystem that manages all projectiles in your game (including tick rates and line traces for collision checks). You can try to use async line traces to free up the game thread, but note that you’ll get the result with one frame of lag in that case.

Don’t spawn static mesh components or particle systems per bullet if at all possible. I’d have one Niagara system that spawns a particle per projectile and is then reads the relevant mesh and position data either via user parameter or (even better) via custom data interface.

3 Likes

Mass framework. I am unaware of that. I will look into that.

I’d have one Niagara system that spawns a particle per projectile and is then reads the relevant mesh and position data either via user parameter or (even better) via custom data interface.

How do I make Niagara particles interact with mesh data via data interface in C++? Is there any example.

The particles wouldn’t interact with the meshes in your level, but can be used to display them. So for example you can set an array with positions as user parameter on your Niagara system, then use that in an emitter to render the bullet meshes and traces.

The actual gameplay logic for collision and movement should happen in C++, e.g. in a Mass component.

2 Likes

Got it. Let me try that. Thanks for answering

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.