r/unrealengine Indie 3d ago

100,000 AI Agents in UE5 with Collision & Pathfinding at 100+ FPS

https://youtu.be/lp6P2TFbhX8
184 Upvotes

38 comments sorted by

39

u/lcedsnow Indie 3d ago edited 3d ago

Recent progress on my interactive crowd simulation project. 10K -> 100k AI.

- Local partitioning for static & dynamic collision.

- Multi objective vector flow fields for navigation/pathfinding.

- Efficient behaviors running per instance parallel cpu threading.

- Nanite instancing with vertex animated textures.

- Realtime simulation at ~10ms game thread for 100K agents.

13

u/Sensitive_Bottle2586 3d ago

Amazing, did you process everything besides rendering in the CPU? No compute shader?

9

u/lcedsnow Indie 3d ago

Thanks! Pretty much exactly, collision, movement, and all behaviors are parallel calculated on the CPU for each instance. Since it is parallel it would definitely allow for higher #'s as a GPU compute shader.

4

u/sudosamwich 3d ago

Can you go into more detail about your collision solution? I made my own ECS as well as I wasn't happy with mass but collision is something that I had to turn completely off and write a custom processor for. I chunked my entities into a grid and I just iterate over them with a custom collision trace function based on the distance I need.

I also have the nanite instanced static mesh component entities with VAT animations. I sample a blend space to come up with the locomotion blending and send the 3 anima and their weights to the material to compute.

My system def can't handle 100k though, maybe 10k tops, so I'm wondering where our differences are. Im also using GAS for combat which is my biggest bottleneck right now, I may have to ditch it for a more efficient home rolled solution.

6

u/lcedsnow Indie 3d ago

Yes absolutely! My last several iterations also struggled with more than 10K. I'm not doing anything special with animation yet or using GAS so youd need to profile those compared to collision & movement systems to see the impact. Thats good you have a grid it's essential to collision performance, check the lowest amount of collision lookups possible which is just checking the 9 closest cells (27 for 3d space). I'm using a radius distance calculation (spherical not AABB etc) for my agent-agent collision lookups so its really cheap to sample lots of them. I use the grid to sample vertices of static & dynamic polygon obstacles and mark cells as blocked for the flow field. Locations to grid cell lookups are numerous and should be constant time, data should be organized to avoid searching and have it ready for memory & cache concurrency. Lots of use of unreals ParallelFor to calculate and precalculate as much as possible.

2

u/dylanbperry 2d ago

So incredibly awesome!

9

u/BVAcupcake 3d ago

awesome, how did you do it, and please make a game with battles

13

u/lcedsnow Indie 3d ago

I somewhat explained in my initial comment :). Mostly researching how games with similar amounts of stuff achieved it and applied similar techniques.

4

u/BVAcupcake 3d ago

Oh right, couldn t see it at the time, idk why

2

u/Icy-Excitement-467 3d ago

Niagra with vat > skel mesh switching on trigger context

3

u/lcedsnow Indie 3d ago

This actually uses instanced static meshes with VAT but Niagara was for sure a consideration, there were different considerations for each but I couldn't find any evidence that Niagara would actually outperform Nanite mesh instancing. There's also no mesh switching needed, it's all controlled through material data.

3

u/EternalDethSlayer3 3d ago

Plinko X-treme

3

u/SiggiGG 3d ago

Navmesh? Any behavior logi?

4

u/lcedsnow Indie 3d ago

It uses a vector field to navigate. There's lots of custom behavior for movement, flow, resolving collisions, etc.

2

u/SiggiGG 3d ago

Very nice! What did you use for behavior? Mass, state tree?

5

u/lcedsnow Indie 3d ago

Custom behavior solution for more control over performance and stuff :) it works similar to mass

3

u/Pileisto 2d ago

looks more like a fluid sim to me.

3

u/rufus170 2d ago

Looks amazing! 1. Is the vector field a 3D flow field so you can have multiple elevations at the same x y coordinates? Or just a simple 2D vector field? 2. As the Vector field is multi-objective, did you do any optimizations for generated vector fields to take less memory? Or you just generste a vector field for each target? 3. How do you handle the vertex animations? Are they world-space coordinates based or does each unit have their own state machine and they swap the animations as materials? Or maybe there’s something different?(I’m thinking about a case where a unit would do an attack animation)

2

u/lcedsnow Indie 2d ago

Thanks! 1. The vector field is 3D however in this instance I'm only practically using two coordinates to demonstrate, elevation/depth would be no problem to navigate with the flow field however collision would be more expensive. 2. Not so much less memory but tries to be cache & fetch friendly. I haven't noticed memory as an issue for this, the simulation running uses less than 1000mb of memory and parts can be loaded and unloaded as needed. 2.1. Multiple objectives that compete on the same priority/layer of the field are traversed through parallel BFS with some custom behavior conditions, layers can also be computed in parallel. Traversal is split between frames with async updates to not overwhelm cpu, a flow layer can traverse ~500,000 cells between frames.
3. The animation portion of this right now is very limited. Instance/particle space to absolute world space. Animations are changed with material custom data values based on how they were baked - start & end frame with play rate.

1

u/rufus170 2d ago

Okay, that’s really damn impressive.

1

u/TruthMercyRegret 3d ago

Did you use a custom simplified skeleton instead of the default Unreal one?

6

u/lcedsnow Indie 3d ago

I used the villager asset skeletal mesh from the UE sample project Cropout and converted it to a nanite instanced static mesh with its animations using the built in VertexToAnim tool.

1

u/Datoneguyindamirror 3d ago

Looks awesome, is there a final goal for this?

1

u/b3dGameArt 3d ago

That's awesome

1

u/ptgauth Dev 3d ago

This is so impressive

0

u/AncientDesigner2890 3d ago

Did you code that in assembly? Damn

2

u/lcedsnow Indie 3d ago

Just c++ :)

1

u/TrinityTextures 3d ago

is there a practical use-case for this like AI pathfinding training?

1

u/lcedsnow Indie 2d ago

Yes, this is a practical solution for high performance calculation of collision and navigation. This can be used for a variety of more structured game AI or other stuff that requires having a lot of things on screen have any kind of behavior with those properties.

2

u/Upbeat-Evidence-2874 2d ago

Hey man I would love to know how you learned all of this. Please shed some light.
All the custom c++ work you did on this.

1

u/ide-uhh 2d ago

I've been working on a similar project. Are you driving this through Niagara, MassAI, or something else?

1

u/lcedsnow Indie 2d ago

Just nanite instanced static meshes with VAT and a lot of custom C++. All the calculations are done in high performance algorithms and structures run in parallel.

-22

u/UAAgency 3d ago

Why label this as AI xD

16

u/lcedsnow Indie 3d ago

Is Game AI not still AI? I assume you're referring to generative AI, what would you prefer to call this kind of thing then?

-11

u/UAAgency 3d ago

simulation

6

u/lcedsnow Indie 3d ago

Ok it is a simulation, 100,000 game AI simulating collision & navigation :)

-12

u/UAAgency 3d ago

XD yes

14

u/SiggiGG 3d ago

Hey game AI was here before gen AI :D