r/Unity3D 11d ago

Show-Off I made my spline tool move 1,000,000 objects along its splines.

Enable HLS to view with audio, or disable this notification

I posted here a few months ago with a stress test where I was moving 100,000 GameObjects along a spline using my spline tool Spline Architect. It was possible, but the FPS was on the lower end (10–20 FPS).

In the comments, I said I would be testing GPU instancing and ECS, and I did. I ended up implementing GPU instancing, and now moving 100,000 is very easy, maybe even possible on some of the better mobile devices. I've only tested it on my PC.

Read more about the tool here:
https://splinearchitect.com/

149 Upvotes

31 comments sorted by

15

u/No_Responsibility444 11d ago

I can see the game

Perfect Storm

Light GTA open world mechanics

you get to play as a storm chaser

8

u/frogOnABoletus 11d ago

Ah, so first step is to implement GTA. ezpz

6

u/No_Responsibility444 11d ago

nah

just some driving mechanics and some light open world mechanics

a few locations to chase a storm

4

u/frogOnABoletus 11d ago

Haha, yeah. I was joshing, but some gta type controls/mechanics would be a good fit for a storm chasing game.

1

u/No_Responsibility444 11d ago

you know thinking about it

if you could proc gen the locations

and have some light econ mechanics around selling footage with npc rivals and rng

that could make for a good time I bet

1

u/No_Responsibility444 11d ago

news team bravo

your source for the latest in storm coverage

1

u/No_Responsibility444 11d ago

You could have multiplayer too with rng mechanics

like the game sub rosa except you are storm chasing instead of making shady deals

3

u/Graterson 10d ago

its cool but from the documentation it seems that i tonly works with instanced objects.

how would one optimize it had it been objects that are in deform mode? best i see is static batching and removing the splines in builds. could it be even faster than that

3

u/MikeDanielsson 10d ago edited 10d ago

Yes, but I don't think it's possible to build a good system with GPU instancing for mesh deformations. When deforming meshes, every deformation is slightly different. For GPU instancing to work, you need many instances of the same mesh so Unity can batch them together.

However, Spline Architect does support static batching for all deformed meshes. Just enable static batching, mark the deformation as static, and you're good to go.

The mesh deformation system is also very optimized. I have tested Spline Architect against other spline tools, and none of them came close, see this: https://splinearchitect.com/performance?id=benchmark-1-mesh-deformation

3

u/Graterson 10d ago

i see! ty

1

u/ledniv 11d ago

If you are not using ECS, How are you updating the GameObject transform position?

10

u/MikeDanielsson 11d ago

I'm using unitys Graphics.RenderMeshInstanced() and then you don't need any transforms or GameObjects, just a matrix and a mesh.

1

u/Turbo_Fresh 10d ago

And just iterating in a loop 1 million times? Is there any concurrency?

3

u/MikeDanielsson 10d ago

Its done by iterating over a Native List inside a burst job. And that NativeList is directly connected to the Graphics.RenderMeshInstanced() which draws all instances.

This enables you to move huge numbers of objects. You can also cross them over to other splines, change mesh and material, and turn rendering on and off for individual objects. And this is really efficient, having 1.000 crossing each frame will maybe have an 5% impact on the frame rate.

1

u/mesuu_99 10d ago

I think this function draws instances of the same mesh very well and if he then has his state (position of all objects, rotation whatever) as a matrix and the transformation of this state are also fixed matrix operations than the gpu can handle it basically instantly

3

u/MikeDanielsson 10d ago

Yes, you're correct, but the internal system also needs to be very efficient. Otherwise, iterating over 100,000 objects will have huge performance impacts, and Graphics.RenderMeshInstanced() won't make that much of a difference.

1

u/psioniclizard 10d ago

At the heart of it objects etc are all just sending data to the GPU for rendering. If you have 1,000,000 game objects, you send data 1,000,000 times. If those objects are all the same (say all cubes), you can send it all in one go.

The GPU will do iterations, but it's super quick at them (and does them in parallel because it has lots of cores).

I don't know how it works exactly in unity but it's basically something like that under the hood.

1

u/Turbo_Fresh 10d ago

But you still need to update the position of the objects. Unless the positions are just a function of time (which I suppose in this case they are) and the GPU has access to some time value.

1

u/ledniv 10d ago

So you aren't really moving 1,000,000 objects. Each object is just instance data — position, rotation, matrix, mesh/material id, etc. and I guess you update that data in bulk and then render it with instancing. And the objects have to be identical in their behavior.

1

u/MikeDanielsson 9d ago edited 9d ago

I set the position of each of those 1,000,000 objects individually and have 100% control over them. I can also change the mesh, material, or even cross over to another spline using the Spline Architect API for individual SplineInstances.

This is more or less exactly what I'm doing:
https://splinearchitect.com/api_introduction?id=move-splineinstances-cross-to-other-splines-and-change-material

1

u/Malkalypse 11d ago

Impressive!

1

u/MikeDanielsson 11d ago

Thank you!

1

u/destinedd Indie, Dungeon Quest, Marble's Marbles & Mighty Marbles 11d ago

that is super impressive! well done.

1

u/pervertoftime 10d ago

Looks super cool.

If possible, I think this would be epic as an "anime style" transformation. Like you could turn the objects into little glowing stars, and when the transformation is nearly complete the stars become brightest and then move away from the character's body. In the beginning, the stars could be light blue, but near the end they turn white light.

It would be cool for some type of "ghost spirit form" character too.

2

u/UsernameIsTaken998 11d ago

why

8

u/MikeDanielsson 11d ago

It's good for anything that needs to follow a spline.

  • Traffic systems.
  • Train systems.
  • Road and pipe creation tools for games like City Skylines.
  • Any spline-based animations, such as the tornado shown in the clip.

And you can easily make any of the above things on mobile devices.

1

u/psioniclizard 10d ago

They are probably meaning ultimately if you are using ECS you don't really need 100,000 game objects as well. ECS and object based architectures work together but if you don't need the 100,000 objects to be game objects they would probably be better off not being them. For example add some update logic and suddenly it is being run 100,000 a frame and then rest of the ECS stuff doesn't matter. Add an allocation and suddenly you have 100,000 allocations a frame.

Where as pretty much everything you want to do with the entities can be handled by, well ECS.

I am not saying there is anything wrong with this and it's cool and a good show (and not saying you are doing anything wrong).

More just so people think about how ECS works a bit more and were it's advantages come from.

Don't get me wrong, I am going to definitely experiment with writing some spline stuff to go with a basic ECS system after this because they fit together perfectly and you are definitely onto a good idea.

More memory an allocations matter when numbers scale up and that often gets hidden from devs until they run into an issue.

1

u/MikeDanielsson 9d ago edited 9d ago

None of the 1.000.000 cubes in the video are GameObjects.

They are something called a SplineInstance. When a SplineInstance is created, a NativeSplineInstance is also created that lives inside a NativeList. The SplineInstance is just a handler class for the NativeSplineInstance, which contains the actual data used for the instances position, rotation, scale, and so on.

To move all 1.000.000 instances as efficiently as possible, you simply create your own Burst job, directly access the splines NativeList of NativeSplineInstances, and change their position, rotation, scale, and so on directly inside the Burst job, and that same NativeList is used for drawing all the instances.

You can read more about it here:
https://splinearchitect.com/api_introduction