Search Unity

Having hundreds of objects in one scene...

Discussion in 'Scripting' started by Bunzaga, Apr 25, 2009.

  1. Bunzaga

    Bunzaga

    Joined:
    Jan 9, 2009
    Posts:
    202
    I have been doing several tests over the last week for creating my tower defence game, and it seems that although my draw calls are low, the amount of objects in my scene is slowing down my FPS.

    I have already combined the tower mesh inside 3ds Max, so that it is one single mesh, which uses bones+rigid skin for the animations. I also combined the parts for each texture into one single 512x512 diffuse texture.

    This increased FPS a LOT, but now I am finding my actual object count is reducing the FPS.

    So are there any good tricks to being able to have around 300 or more objects on the screen, most of them with some form of movement either through a rigid body LatUpdate, or else stationary but with a bone animation?

    The towers are stationary, but have animations, the creeps are animated plus have a character controller for movement, and the missles/projectiles/lazers, etc either have rigid bodies, or some other form of movement applied to them.

    Something like a RTS type scene where you could have hundreds of units all on screen at once.
     
  2. Bunzaga

    Bunzaga

    Joined:
    Jan 9, 2009
    Posts:
    202
    Here is an example of what I mean (attached).

    There are 40 towers, each one has the potential to shoot up to 4 rockets.

    The FPS in this scene pulses from 90+ down to around 20.

    I'd like to really push the limits. Is there a better way to do something like this?
     

    Attached Files:

  3. TwiiK

    TwiiK

    Joined:
    Oct 23, 2007
    Posts:
    1,729
    Stay away from the character controller and you'll be fine. :) I had the same problem.

    Low amount of draw calls, nearly no textures, maybe no more than 10k triangles in the scene at the same time and still horrible framerate on my machine (which is a beast. :)) with only 10-20 enemies at once.

    I then swapped out the character controllers on my enemies and instead turned my enemies into rigidbodies which I moved with MovePosition (http://unity3d.com/support/documentation/ScriptReference/Rigidbody.MovePosition.html) and suddenly I could handle hundreds of enemies at once.

    I suspect the character controller is very expensive and should only be used for the player himself. Also, the fact that it forces a capsule collider is pretty lame as well. :)

    You could just try removing the character controller (or all scripts all together if you have other possibly expensive things going on) on all your enemies and see what kind of framerate you get.

    300 objects will be hard to handle no matter how you approach it. If I'm not mistaken it's 300 draw calls at the minimum and with just 1 directional light it's 600 draw calls.
     
  4. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Graphics wise looking at the stats window it seems like the graphics requirements are fairly low, so thats not your problem.

    I would suspect that some of your scripts might have some performance issues.
    Try plugging some of the behaviours that are used a lot into this Profiler from the Wiki and see if you can figure out what is causing the slowdowns there:
    http://www.unifycommunity.com/wiki/index.php?title=Profiler
     
  5. Bunzaga

    Bunzaga

    Joined:
    Jan 9, 2009
    Posts:
    202
    I tried to use that profiler thing, but most of my code is with Javascript. I keep getting an error "Unknown Identifier: 'Profiler'". I hate to assume what this is caused by, I'm hoping someone could point out what I'm doing wrong?

    I just put the Profiler.cs file in my project root, and made a js file:
    Code (csharp):
    1.  
    2. #pragma strict
    3.  
    4. private var outputTest: float = 0;
    5.    
    6. function Start()
    7. {
    8.     Profiler.StartProfile("Start");
    9. }
    10.    
    11. function Update ()
    12. {
    13.     Profiler.StartProfile("Update");
    14.     for (var i: int = 0; i < 100; ++i)
    15.         outputTest += Mathf.Sin(i * Time.time);
    16.     Profiler.EndProfile("Update");
    17. }
    18.    
    19. function OnApplicationQuit()
    20. {
    21.     Profiler.EndProfile("Start");
    22.     Debug.Log("outputTest is " + outputTest.ToString("F3"));
    23.     Profiler.PrintResults();
    24. }
    25.  
    Obviously I never declare or instantiate 'Profiler' in my script, but I thought it was a static class? Anyway, let me know please.