Is it safe to parallelize SetActorLocation() with separate actors?

I’m making a bullet hell and want to call SetActorLocation() for thousands of enemy bullets. However this is obviously slow and so I’ve thought about splitting up the calls to SetActorLocation() using FAsyncTask.

However, I’ve heard that SetActorLocation() isn’t thread safe, but I assume that is for multiple calls of the same actor. I’m wondering if its still unsafe if called for separate actors?

I’ve tried using it with separate background tasks with separate groups of actors, and got exceptions when collision events happen that try to delete the bullets (when the player collides with them). These only happen with 2 or more tasks. 1 task is fine. This tells me something must be getting botched when SetActorLocation() is used in parallel, even with separate actors, but I want to be sure.

First: Is it? Create 1000 spheres that are all physically simulated, and run the simulation, compare your performance to that. If you have the same performance, you already have the max performance you can get for using positional actors for bullets.

Second: Actors that move need to also invalidate a bunch of world management data structures, as well as update the networking view in case they’re being replicated. Thus, I would not call SetActorLocation() from a thread other than the game thread.

Third: If you have so many bullets, how can the player even see them all? Do they all have a lifetime? Do they all run collision? If they all run collision, that’s likely a LOT more expensive than the simple SetActorLocation() call, so I’d highly recommend using a profiler to figure out what’s actually slow, if you’re having a problem. And if you don’t have a problem, don’t complicate things.

I’d probably go with a single actor acting as the “rain of bullets”, propelled by a ProjectileComponent. Maybe there’s even a solution in the Niagara particle system to do the visual effects for the bullets.

I’ve already profiled prior and found the SetActorLocation() to be the bottleneck, and yes, the bullets have collision components, usually spheres and boxes.

However, I am considering other optimization options, via culling based on distance from the player. I’m content with not using the threading option, since as you said, it’s not a good idea.

Bullets are rendered with instanced rendering, which is already very fast. And some have lifetimes as well, but that doesn’t factor in much.

Thanks for the help!

You can try disabling collision and check IsPointInBoxWithTransform, point being the bullet, and box being your character’s hit box. I don’t know how expensive that it, but if you’re already setting location on tick, maybe checking that location against the hitbox won’t be too expensive. But it will allow you to disable collision to free some resources.