Author Topic: Developing an RTS game using Unity any advice?  (Read 6873 times)

Offline Arowx

  • Newbie
  • *
  • Posts: 1
Developing an RTS game using Unity any advice?
« on: October 28, 2013, 11:52:15 AM »
Hi I'm an Indie game developer using Unity but I keep trying to make games that seem to push Unity too far and quickly hit performance problems.

For example I have a simple RTS style game "Zombie Invasion of Eggland" but I would really like to improve it's performance so I can have more Units in the game and a larger play area.

Currently I use the standard Unity toolset Physics, GameObjects and default shaders. 

I also use the A*Pathfinding system from the asset store.

Arcen have managed to get Unity to work with massive space armadas, what advice could you give, are there designs/architecture that could take this from a small RTS into a larger open world game with many more Units or in this case massive hordes of zombies?

On a side note what do you think of the new Unity 2D pipeline?
« Last Edit: October 28, 2013, 03:54:36 PM by Arowx »

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,059
Re: Developing an RTS game using Unity any advice?
« Reply #1 on: October 28, 2013, 12:11:22 PM »
1) Use A* sparingly.  AI War gets away with a small pathing map as in-system pathing is strait-line from A to B.  The only pathfinding that needs to be done using A* is between-system, which has a cap on the number of nodes (120) which is blazingly fast.  Keith might even have dropped A* and instead used precomputed pathing (due to the fact that the walkable map is so small, so the memory overhead is negligible).

2) Lean how to optimize your rendering.  The more draw calls you have (look at the profiler) the slower it's going to run.  Every iteration of Unity has gotten better in this respect, especially when it comes to particle systems.  3 has the oldest and most intensive, 4 has the newest and fastest.  Ideally you should be using a single draw call for ALL your particles.

3) Learn how to optimize physics.  Mesh colliders (which are the default for flat planes--no idea why--and imported objects) are very very good for non moving objects.  When a mesh collider moves or rotates it needs to be recomputed (no a fast thing to do) as there are no shortcuts the way a cube, sphere, or capsule collider have.

4) Avoid trigonometry.  Any floating point call to Math functions is intensive enough to add up for hundreds of objects per frame.  Additionally using bitwise operators in large enough numbers has an impact.  There was once a discussion on the Logistics station in AI war using +100% / -50% speed modifiers because Keith was using bitwise << and >> to multiply and divide by 2, because any other math function there (even replacing with *2 or /2) would cause noticeable lag.

5) The most generic note: More code does not mean slower code.  Learn to use if-shortcuts and use them liberally.  Any place you can determine that a complex function does not need to run using a faster method, do it.  For example, limiting repath checks to once every 5 or 10 seconds.  Players are unlikely to notice zombies pathing the "wrong" way for a short time, and if they do, call it a feature: Zombies are freaking dumb.  By reducing the heavy load in this manner more specialized/rarer units can path more often (any more than twice a second isn't going to be noticeable, though, so even here you can save!), giving the illusion that they're more intelligent.

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,216
  • Neinzul Y PzKpfw Tiger!
Re: Developing an RTS game using Unity any advice?
« Reply #2 on: October 28, 2013, 02:11:11 PM »
Hey Draco, can you tell us some more about 4) ?
Quote
4) Avoid trigonometry.  Any floating point call to Math functions is intensive enough to add up for hundreds of objects per frame.  Additionally using bitwise operators in large enough numbers has an impact.  There was once a discussion on the Logistics station in AI war using +100% / -50% speed modifiers because Keith was using bitwise << and >> to multiply and divide by 2, because any other math function there (even replacing with *2 or /2) would cause noticeable lag.

For dummies like me, for example...what's the right way to do it, what's the wrong way?
The beatings shall continue
until morale improves!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,059
Re: Developing an RTS game using Unity any advice?
« Reply #3 on: October 28, 2013, 06:01:34 PM »
A classic use of trig is to get one object to move towards another object on non-orthographic path (i.e. not horizontal, vertical, or 45 degree angle).

The trig way to figure out how far to move is this:

Code: [Select]
var theta = Math.atan2(this.y - targ.y, this.x - targ.x);
var sx = speed * Math.cos(theta);
var sy = speed * Math.sin(theta);

Note that this uses three trig calls.  Instead we can do this:

Code: [Select]
var dx = this.x - targ.x;
var dy = this.y - targ.y;
var dist = Math.sqrt(dx*dx + dy*dy);
var sx = speed / dist * dx;
var sy = speed / dist * dy;

Instead of three complex math calls, now we only need one due to the Law of Similar Triangles.  Of course, you can speed this up even more by approximating the square root (left as an exercise to the reader).

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,216
  • Neinzul Y PzKpfw Tiger!
Re: Developing an RTS game using Unity any advice?
« Reply #4 on: October 29, 2013, 04:50:34 AM »
That might actually be a real performance saver for my projects...thanks! I didn't know Mathf was so much trouble for the CPU.
The beatings shall continue
until morale improves!

Offline keith.lamothe

  • Arcen Games Staff
  • Administrator
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,504
Re: Developing an RTS game using Unity any advice?
« Reply #5 on: October 29, 2013, 10:34:16 AM »
Yea, avoid sqrt where you can too, but sin and cos are even worse.  If you're curious, here's our main distance-approximation method for when it doesn't have to be exact (which is like 95% of the cases we run into because we don't mind cheating a little) :

Code: [Select]
    public static int ApproxDistanceBetweenPointsFast( int P1x, int P1y, int P2x, int P2y, Int32 ShortcutsBeyond )
    {
        Int32 dx = P1x - P2x;
        Int32 dy = P1y - P2y;

        if ( dx < 0 ) dx = -dx;
        if ( dy < 0 ) dy = -dy;

        if ( ShortcutsBeyond > 0 )
        {
            if ( dx > ShortcutsBeyond || dy > ShortcutsBeyond )
            {
                if ( dx > dy )
                    return dx;
                else
                    return dy;
            }
        }

        Int64 min, max, approx;

        if ( dx < dy )
        {
            min = dx;
            max = dy;
        }
        else
        {
            min = dy;
            max = dx;
        }

        approx = ( max * 1007 ) + ( min * 441 );
        if ( max < ( min << 4 ) )
            approx -= ( max * 40 );

        // add 512 for proper rounding
        Int32 val = (Int32)( ( approx + 512 ) >> 10 );
        if ( val < 0 )
            return -val;
        return val;
    }

You can omit all the "ShortcutsBeyond" stuff (or just pass in -1 for that to suppress it) but that lets it use an even dead-simpler approach for when you want to say "and if it's greater than X I _REALLY_ don't care what the actual distance is, just tell me that it's greater than that".

On the other hand, you could simply pick a design that doesn't involve so very many actors, and then you can use sqrt and trig all you like.  It can also be more comprehensible to the players that way.
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,059
Re: Developing an RTS game using Unity any advice?
« Reply #6 on: October 29, 2013, 11:22:24 AM »
Yea, avoid sqrt where you can too, but sin and cos are even worse.

If one square root is faster than one trig, then it's definitely faster than three. ;)

But yes, avoid square roots whenever possible.  When doing distance checks myself, I calculate against the square.

That is, "is the distance greater than 4 units away" is exactly equal to "is the square of the distance greater than 16 square-units?"

*Scribbles on a piece of paper*

Ha!  You can actually drop the square root in my previous code fragment. :D
Ah the glories of math.  I'd forgotten about that and didn't check first.  If 3/4 is equal to 6/8 (3/4/5 triangle similar to a 6/8/10 triangle) then 9/16 is equal to 36/64.

Offline keith.lamothe

  • Arcen Games Staff
  • Administrator
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,504
Re: Developing an RTS game using Unity any advice?
« Reply #7 on: October 29, 2013, 11:28:17 AM »
Ah, right, if it's simply a greater-than (or less-than) check you can just go off the square, yea :)  We tend to do more stuff where we care about the number to some extent.

And in those cases where one literally doesn't care about the number if it's "greater than or equal to Hrair" you don't even have to do the square thing, just check against dx and dy and you only have to pull out the multiplication if neither of those trips the threshold.  So just a couple sub instructions and some branch-if-greater, etc.  How much that matters depends on how many cycles the mul instruction takes in your case, I suppose.
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,059
Re: Developing an RTS game using Unity any advice?
« Reply #8 on: October 29, 2013, 12:17:41 PM »
Quite.
Which harks back to Tip 5: More code is not slower code. :)

If a single multiplication line is called often enough to be a noticeable performance impact, then not-doing it by checking against some other value first will save CPU cycles.