Hello!
I had a different kind of question about unity
Can it handle large scale rts battles in one map like lets say i have 1500 soldiers in army i created and my friend has 2000
Yes, but then it’s no longer a question of can Unity do it, but more how good you are at optimization as those numbers will bring any engine to its knees without a great deal of skill available.
My understanding is that Unity cannot handle high quantity simulations, at decent frame rates as it does not support:
Hardware instancing, a way to reduce draw calls when lots of animated characters are used together or have native support for Imposters, a technique used where a 2d sprites are generated from models and used to represent characters in the far distance.
Multithreading of gameObjects to allow the soldiers to be run controlled by separate cores and increase the simulations speed.
Just try it for yourself with an army of cubes how many can you run on a terrain at 60fps.
Made a very quick test, using unity terrain, cubes with sphere + colliders + rigidbodies.
Two armies of 1000 cubes marching towards each other and as you can see Unity gets 2.0 fps on my PC.
Man. You wouldnt use rigid bodys for characters on a scale like that… The best solution would be your own physics system. Unity has nothing to do with any of this… An example of how you could easily get a large amount of characters on their feet running around would be to have each character do a raycast downward and position the character at the hitpoint of the raycast+the height of the character. But point is, of course unity doesn’t have systems in place for large scale armys, Total War has been building their engine for this exact purpose for a very long time.
But, nothing is impossible, when you take matter into your own hands, and don’t rely on an engine to have built in features for every game type and scenario.
On the plus side the same simulation with two armies of 500 or 1000 units total runs at 60fps, but once you start adding particles, models animations, ranged units, units of different types, and this number will drop if your aiming for 60fps.
So the simple answer is No, Unity cannot handle > 1000 units moving over terrain using it’s physics system.
But as brilliantgames points out if you can write your own “physics” system then you could have more units moving over terrain.
Don’t feel the need to defend Unity on this. No, Unity can’t handle 3500 units onscreen at once, because it’s primarily meant for small developers who have the common sense to know that a massive-scale RTS isn’t within their budget. Even if you were good enough at programming to optimize for this sort of thing, Unity would only be getting in your way and you’d want to roll a custom engine.
OK, Changed the test over to Kinematic Rigidbodies that follow the terrains height (terrain.SampleHeight(pos)) and have managed to get 2000 units marching into each other at 40-50 fps and still detecting collisions (in webplayer/pc build).
And on a PC standalone build got 2 x 2000 units charging at each other at about 25 fps.
I think there are still some optimisations that could be made to this, so it might be just about possible to hit 4000 units in combat at 30 fps, but you are going to have to do some serious optimisation work to get this type of game out of Unity.
Interesting. Just some thoughts…
- How often are you checking each unit to see if it needs to fight/interact with another nearby unit? Every frame, once every second, etc?
- I wonder if using Graphics.DrawMesh would be a little faster than letting Unity handle them as GameObjects. Probably would just remove the instantiate cost, but still might be worth looking at.
- I’ll bet LOD groups would help a lot here.
I guess I’m curious about how much goes into just drawing the units themselves, and how much goes into calculating their activity.
Using just cubes, unity manages to get the whole scene rendered in 20 draw calls, the physics engine is checking for collisions and is running at the default physics update frequency.
Looking at the profiler the scripts that march and terrain follow for each unit are called 4000 times each and take up a good chunk of the frame rate.
So having a single march/terrain follow script or two could greatly reduce overheads.
An RTS, especially a multiplayer on like in the OPs example has to be lockstep, you can’t use the Physics subsystem at all for anything but client-side visuals.
It’s a given that you’ll need to make design trade-offs to get those numbers:
- flat terrain or a fast heightmap lookup so you don’t do a raycast per unit to get correct terrain hugging
- tons of atlased imposters
- grouped AI so you treat globs of AI as one unit where feasible
- per-unit AI will of course have only minimal intelligence
Updated above weblplayer version hit’s about 40fps (for me)
Now has a central single update function to move and terrain follow the units.
Link to 4000 units webplayer simulation
Standalone version only manages 50fps.
@Cannon - Yes I think a faster terrain lookup could boost this even more possibly taking it to 60fps.
Yeah, it probably would take it past 60.
There’s also a couple of tricks too to get around the skinning issue for Shogun style games (tricks with swapped rigid meshes come to mind).
An extreme upper bound for a Unity game is probably AI Wars, which goes up to 30,000 units at one time. There’s a lot of fun trade-offs between quality and quantity that can be made to scale the game from 10 units to 30,000.
While I can share no details as it was a professional gig, not that long ago I wrote a simulation with 30,000+ agents running around which ran at 30+ FPS on an old Pentium 4 machine we had at the office.
Like brilliantgames says, yes Unity can do it, you just don’t want to use their off-the-shelf general-purpose solutions to do the whole thing - this kind of scale is not what those general purpose tools are for.
Its certainly possible but it takes a lot of work. http://www.youtube.com/watch?v=AwVmLTNwvOg <— its not a game but has 5k characters.
An RTS doesn’t have to be lockstep, it just so happens that most of them are. Planetary Annihilation is using an asynchronous client-server model with great success, especially for an alpha build.
Yes, I’ve overgeneralized, that’s true.
PA is rather unique though. From what I’ve heard their design does impose limits on what they can do with gameplay, and I highly suspect that they still do run a deterministic Physics simulation (which Unity does not; not even trig functions are the same between platforms let alone PhysX) just to limit the amount of synchronization that they have to do. These are just my guesses though; I’m intensely curious as to how they do the synchronization with no unit cap.
Had a play with using the array data from the terrain to set the unit heights but it did not easily follow the terrain, as using integers to look up the position and no interpolation between surrounding points. Units were slightly out of sync with the terrain. Climbing before the terrain appears and descending under the terrain.
So in conclusion, out of the box, Unity’s generic components do not currently allow for massive RTS battle simulations at 60fps.
You would probably have to build your own engine to power an RTS type game, or there may be other engines that are built to provide the features you need.
Or you could limit your unit counts to hundreds of units and make a reasonable RTS simulation system with Unity.
If Unity’s core engine was multi-threaded with load balancing would that improve things?
If you want that kind of scale you probably wouldn’t let a battle “play out” half as much as you’d orchestrate it.
A troop doesn’t fall after being hit by a stray bullet, the engine decides that troop is going to fall and then it fires the bullet at him.
You wouldn’t need to test for collisions if you’re explicitly creating them.
I’m speaking as a complete noob though.
Don’t bother trying NavMesh either. I used it and that’s one of the reasons I can’t continue with this…
http://forum.unity3d.com/threads/164201-Castle-Wars-Projects-page?p=1121996#post1121996
It can barely handle 100 let alone 1000. If you were using maybe an A* solution it may be better.