Hello,
in a recent effort of gaining performance when moving 5000 enemy units (gameObjects, RTS like game) through one manager script (DOD style), i tried different approaches, including: JobSystem+Bursty, and GPU multithreading with HLSL compute shaders.
Trying both options, i found the compute shader approach pretty interesting- to me, this was not only far easier to implement than the JobSystem (where i still struggle with), but the compute shader approach worked right out of the box and seems also very clean and small in terms of code. So with that, i already have successfully offloaded my position calculations to different GPU cores.
GPU multithreading via HLSL compute shaders seems like a potential and powerfull alternative to CPU multithreading!
âŚ
Problem:
So in the current state there is the DOD manager script which passes in all current unit positions in one batch, into the compute shader and uses multiple GPU cores to calculate the new unit positions. It then passes the new positions back into the C# manager (CPU buffer?). People said this eats up performance again, but currently i only see one problem, which causes all performance gains to be lost again: the problem is, i still have to apply the new positions to the gameObjects in a for loop, itering over the array with the new positions and applying the new position to each unit (transform). So in this loop we have 5000 * âunit.transform.position = newPos*â, which eats about 30fps.*
Question:
I know this is where JobSystem would shine. But isnât there a way to move the units through the GPU, so that the compute shader does not even have to pass back the new positions into the c# unit manager?
Demonstration of what GPU power looks like:
(UEBS2, shows millions of 3D animated units in unity):https://youtu.be/kpojDPlIjdQ?t=56 (with time marker)
This proofs that there must be a way to move units via GPU. Maybe they are not GameObjects, but they must have something like a transform, which the developer of above linked video seems to have figured out.
EDIT: after posting, i answered the following questions with ChatGPT. Answers marked green. Still interested if anyone has additional input.
Final thoughts:
-
How to get a âbridgeâ for C# Mono GameObjects, to GPU compute shader (HLSL)?
EDIT: the answer here is Unityâs compute Buffer API, which i have been using. -
Is there even a possible way that HLSL compute shaders or GPU can âtalkâ to MonoWorld GameObjects? EDIT: again Unityâs compute Buffer API
-
Currently, i think the only way may be to have the units fully managed on GPU, so no mono objects exist, as GPU cant access regular (CPU) RAM without buffering back. Or is there a way to get around the drawback of buffering back from GPU to CPU?
EDIT: This approach seems right (managing units fully on GPU and using GPU instancing). For talkback from GPU to C#, one can use Unityâs compute Buffer API. -
This approach seems extremly powerfull, why did Unity not look further into this yet? We already have compute shaders which (if i understood correctly) are exactly for such calculations (Physics for example), if unity could provide a bridge (API) to access GameObjects in MonoWorld (from within the compute shader), then that would open a massive gate for new architectural options! EDIT: here again, the answer here is Unityâs compute Buffer API.
I am interested if some of you guys have stumbled upon the same problem, or if someone maybe has found a solution to this.
Thanks,
Regards!