Performance drops over time on OUYA, not in unity (60 fps -> 15fps)

rhellikrhellik Posts: 28Member

Hi, I have a problem with our game. I've started developing it with unity 3.5 and now after I received my OUYA switched to unity 4.1.

My problem now is after I tweaked many things to get more performance, the frame rate just steadily drop without anything happening really. It's a dual-stick spaceshooter so yes there's usually lots of meshes, shots and particles but I tuned those down a lot.

When I start a level I have about 60 fps and for testing I now have only two enemies spawning and you own ship. After a while (this varies from try to try) it jsut steadily drops down to 20 or even 15 fps and I have no idea why. I'm just flying around and not shooting or anything.

I tried several things but I don't really know how to go on about testing it.
What kind of info would you guys need to help me or give me pointers where to look?
I have some particle system in the background but they are disabled for now. The player ship has an engine particle system. There's a background image that's not moving atm. I don't know what else to try....
I only get these performance drops on the OUYA.

Comments

  • rhellikrhellik Posts: 28Member
    Don't know how to edit post.... I have about 15-20 draw calls.
  • mjoynermjoyner Posts: 168Member
    does logcat show lots of "gc" messages?
  • ShushShush Posts: 178Member
    If it's not Java's garbage collector, then hook up PerfHUD ES and watch what's going on in the performance dashboard, it should be pretty obvious fairly quickly what's going on CPU and GPU sides.

    If you need more info, then the Call Trace under the Frame Debugger will give you an advanced per frame snapshot of OpenGL ES commands/draw calls being sent to the GPU.

    I use it extensively for our own engine and occasionally to check out games I download, it's pretty interesting to see the majority of games that use Unity where they spend their time.
  • rhellikrhellik Posts: 28Member

    @shush: That sounds like something, that would be useful but I don't know what PerfHUD ES is or how to set it up. ^^; Can I use that while the game is running on the OUYA machine?

    As far as I have figured out right now, the frame drop has to do with the extra HUD camera I set up. I then layer the HUD camera over the main camera. There's not that much going on there, just updating some text fields and redrawing some meshes for a circular life bar. I'll have to do more testing to see where the problem lies exactly.

  • ShushShush Posts: 178Member
    https://developer.nvidia.com/nvidia-perfhud-es
    http://docs.nvidia.com/tegra/data/How_To_Analyze_Application_Performance_Using_PerfHUD_ES.html


    It pretty much runs out of the box and yes you use it whilst the game is running on the OUYA. It comes with Windows, Mac and Ubuntu clients.

    If your frame rate is initially good and then slowly dies, it usually suggest Garbage Collection, (as Mjoyner suggested), or poor allocation/de-allocation of resources per frame. Maybe a pivotal data structure, (e.g. cull or render list), is linearly increasing in size as the game progresses. With my games I never allocate/de-allocate resources once the rendering process has begun, everything is pre-allocated/loaded per level/world or streamed into pre-allocated buffers in real  time.

    Anyway, good luck with the debugging.
  • tgraupmanntgraupmann Posts: 2,546Administrator, Team OUYA
    Interested to know what you find...
  • rhellikrhellik Posts: 28Member
    edited July 2013

    It seems to have been a problem with my script for the HUD.

    I had 4 planes that were creating new(!) meshes every frame. I guess I thought the old meshes would be recycled. I modified to jsut change the mesh and not create a new one. Seems fine now, at least no over time creepy slowdown. Just regular ones. ;)

    On that note, I notices that lots of particles can slow down the game quite a bit as well. Is this usual?

    Post edited by rhellik on
  • tgraupmanntgraupmann Posts: 2,546Administrator, Team OUYA
    It depends on what kind of particles, whether they overlap, and how much overdraw is going on.
  • rhellikrhellik Posts: 28Member

    Well, I have a kind of vortex in the background, consisting of two particle systems.
    Without them (and no enemies) I can get 60 fps. When I turn them on, with now about 2000 particles (stretched billboards) I'm down to 40 fps.  I could try and see if it's better without the stretched, but without these particles the game loses something. :/

  • tgraupmanntgraupmann Posts: 2,546Administrator, Team OUYA
    You can bake those particle systems into a sprite sheet. And then you could maybe use 4 animated particles to achieve the same visual effect.
  • Killa_MaakiKilla_Maaki Posts: 504Member
    You can either bake them into a spritesheet, or lower the resolution of your game. I recently did a test of particle systems, and I found that at 1080p a ton of particles will crush your game's performance like a soda can, but at 480p they ran quite acceptably (I had almost 100 particle systems with 20 particles per second, and it ran at 48FPS).
    So maybe 600p would work if you don't want to go too low (600p is AFAIK what CoD runs at on the Xbox 630)
    You didn't remember the plot of the Doctor Who movie because there was none; Just a bunch of plot holes strung together.
  • ShushShush Posts: 178Member
    edited July 2013
    Killa_Maaki is spot on about the OUYA, it's exactly the premise we operated under for our engine and games.

    The OUYA has massive fill rate issues at it's native resolution due to it's limited shared memory bandwidth and unified memory architecture. (It has the approximately the same bandwidth as an original Xbox, one guess as to what the native resolution of an original Xbox was).

    So the biggest fill rate offenders with the OUYA are, it's high native resolution, overdraw caused by poor sorting of opaque draw calls, overdraw caused by alpha enabled particle systems and indiscriminate use of discard within your fragment shader, (discard disables all GPU depth optimisations as the GPU cannot skip the fragment when a discard instruction is enabled).

    There are multiple ways around this, these are the methods we used in order of priority and simplicity. Obviously if you have an engine that doesn't require massive amounts of geometry with complex shaders then most of this advice will be overkill, the bottom line is to always experiment.

    1: Lower the resolution, our engine increases in elapsed frame time,  (i.e. decreases in average fps), fairly linearly with resolution until it hits around 1280*720, (around 30fps average), from there it starts taking a massive non-linear nosedive ending up at 5-6 fps average at 1920 * 1280. At 960*450 it runs at 45fps solid.

    2: Use small feature culling, this technique can be very content specific, (i.e. usually is not applicable to 2D or fixed camera worlds), as your objects decrease in screen pixel area, cull. This generally means that on the CPU side you need to calculate a 2D bounding in box in screen space by applying your model-view-projection matrix to your objects local 3D bounding box. Once the area of the 2D box is lower than a certain amount, (e.g. 3*3 or 4*4 pixels), cull it. The pop up that can be caused by this technique can be combated by alpha fade in techniques, but that can cause even more overdraw and alpha sorting visual issues. We stick with keeping it simple and accepting a small amount of object pop up as a necessity of the OUYA.

    3: This one is completely game/content specific but can be a huge win, use occluding techniques at the vertex and fragment stages to minimise overdraw.

    a) Setup low vertex occluders as part of your content workflow or as a pre-process loading stage for world/level loading, (these can be as simple as world space bounding boxes, but view space bounding boxes generated on the fly are the best option). Then on the CPU side within your culling routines, occlude complex geometry using these occluders in view space. (This one is non trivial and it's benefit is extremely content specific). This culls geometry before the transformation stage, i.e. before it hits your vertex shaders, (the same way FOV culling does), some SGI graphics guru many years ago once said, the fastest polygon you ever draw is the one you don't draw.

    b) Sort your objects first by state, (most expensive to least, i.e. shader, texture, opengl states, etc), then sort by view depth, (this needs to be done per frame obviously). This allows the GPU to cull the rendering process before it hits the fragment shader based on depth. What this does is that it allows the GPU to take massive advantage of the depth buffer and it's hierarchical depth optimisations, instead of most, (or worst case all), of your drawing calls making it to the fragment shader, only the closest draw call, (in view space), makes it there; the rest are culled after the vertex shader.

    Remember for most engines after the resolution abuse, it's abuse of the fragment shader that generally has the most impact on an engines performance.

    3) Be careful with your particle effects, (this one requires lots of trial and error), try multiple techniques, (Point Sprites, dynamic VBO for each particle emitter that is rebuilt per frame, etc). Limit the individual particles size, their quantity and lifetimes.

    Other things to try, (these are mainly to combat visual glitches):
    - Turn off depth buffer writes but enable depth testing and draw your particles last.
    - Sort your alpha particles based on view depth and use standard alpha blending.
    - Don't sort your alpha particles and use a discard shader.
    - Don't sort your particles, use additive blending, (this works great with fire, explosions etc).

    I could go on and on, (but time for me to go to work), the order of the day is to always experiment and iterate over your algorithms and techniques.

    Post edited by Shush on
  • tgraupmanntgraupmann Posts: 2,546Administrator, Team OUYA
    Lots of good info there @Shush thank you!
  • rhellikrhellik Posts: 28Member

    Wow, lots of info. Thanks!

    I already lowered the resolution to 720p but I don't really want to go any lower.
    I'm rather new to Unity, this is my first project, started a few months ago, so I'm not familiar with sprite sheets yet. I know generally what they are, but didn't know you could bake particles into them. How would I do that?

    But will it bring better performance? In my head, a particle is a vertex that defines the position and then a particle halo is drawed at that point. Wouldn't a sprite sheet be doind the same thing? Just more vertices? (4 vertices to a plane) 
    Or how exactly would that work?

  • Killa_MaakiKilla_Maaki Posts: 504Member
    rhellik said:

    Wow, lots of info. Thanks!

    I already lowered the resolution to 720p but I don't really want to go any lower.
    I'm rather new to Unity, this is my first project, started a few months ago, so I'm not familiar with sprite sheets yet. I know generally what they are, but didn't know you could bake particles into them. How would I do that?

    But will it bring better performance? In my head, a particle is a vertex that defines the position and then a particle halo is drawed at that point. Wouldn't a sprite sheet be doind the same thing? Just more vertices? (4 vertices to a plane) 
    Or how exactly would that work?

    In the end, it becomes four vertices (and two triangles) regardless. You just can't draw anything in 3D without using vertices and triangles, there's no way around it.

    Also, you misunderstood. We're talking about baking the entire particle system into a single spritesheet, rather than each individual particle.
    You didn't remember the plot of the Doctor Who movie because there was none; Just a bunch of plot holes strung together.
  • rhellikrhellik Posts: 28Member

    Well I didn't exactly bake them, but I put in a new texture which is animated on a turning mesh, wich gives pretty much the same effect, but MUCH better performance. :)

    Really great help, thanks!

    Now I have another problem. This vortex is shaped like a funnel going down (into the z-plane of the viewer). I want to have the center of the vortex fade to black (-> black hole)

    I tried using one giant particle or using one plane with a texture on it (probably basicaly the same). BUT when I put over the end of the funnel, it's drawn underneath and not on top. Only if I put the plane somewhere in the middle, z-wise, is it drawn on top. Is there a way to tell unity to draw it on top, even if it's further down? If it's that far on top there's a lot of overdraw and OUYA doesn't seem to like that.

  • Killa_MaakiKilla_Maaki Posts: 504Member
    Unity will sort objects by distance. So whichever object's center (NOT pivot, mind you) is closer to the camera will be drawn first. I don't think there's a good way to influence this order.
    Is there a reason you can't put that in the existing vortex texture itself? Would skip overdraw issues altogether.
    You didn't remember the plot of the Doctor Who movie because there was none; Just a bunch of plot holes strung together.
  • tgraupmanntgraupmann Posts: 2,546Administrator, Team OUYA
    Materials have a render queue field that doesn't show in the inspector, but it's scriptable. And that gives you control over the rendering order where you can force it to render on top.
  • tgraupmanntgraupmann Posts: 2,546Administrator, Team OUYA
    edited July 2013
    "Kasper from our Toolsmiths Team wrote a blog post about the test suite that we share with Google and others so they can integration test Unity with Android devices and the Android OS. We are currently looking into finding more potential players who can benefit from this suite, so check it out!:"



    image
    Post edited by tgraupmann on
  • rhellikrhellik Posts: 28Member
    Unity will sort objects by distance. So whichever object's center (NOT pivot, mind you) is closer to the camera will be drawn first. I don't think there's a good way to influence this order.
    Is there a reason you can't put that in the existing vortex texture itself? Would skip overdraw issues altogether.
    Yeah, I put in a second texture (blend alpha to black) on the vortex, hadn't thought of that before. It got better, but there still seems to be some overdraw issue. It still uses a couple fps, so right now I'm deactivating it till I find the bigger culprits. Not sure if its particles or what. Tris alone doesn't seem to be a problem. Had about 100k verts / tris running smoothly.
  • rhellikrhellik Posts: 28Member
    edited July 2013

    I know installed the PerfHUD and let the game run with it.
    There's a lot of stuff going on but I can't really seem to figure out how to read it, or find out what to do with the data. The Frame profiler is pretty empty for me. There's no duration or so I can look at like it says in the manual. Is this dependant on the OUYA system? Can I unlock this somehow?

    EDIT: Ok, I installed the latest version of perfHUD and now at least some numbers pop up. Not all of them but draw call durations. That's really helpful and I'm learning a LOT about rendering on mobile (i.e. OUYA) devices.

    Post edited by rhellik on
  • GuaaGuaa Posts: 4Member
    Can someone tell me how exactly I can force 720p in Unity? I'm not much of a coder, so I would appreciate a detailed answer. 
  • tgraupmanntgraupmann Posts: 2,546Administrator, Team OUYA
    The general answer is you can adjust the Unity player with Screen.SetResolution(1280, 720, true). And then you have to call the Java backend, resize the view, and the display.
  • Killa_MaakiKilla_Maaki Posts: 504Member
    The general answer is you can adjust the Unity player with Screen.SetResolution(1280, 720, true). And then you have to call the Java backend, resize the view, and the display.
    How do I call the Java resize stuff? I haven't been doing that so far, and it's messing with the mouse (but otherwise seems to resize fine?)
    You didn't remember the plot of the Doctor Who movie because there was none; Just a bunch of plot holes strung together.
  • tgraupmanntgraupmann Posts: 2,546Administrator, Team OUYA
    Take a look at OuyaSetResolution.cs the resize example.

    Which does:

    Screen.SetResolution(1280, 720, m_fullScreen);
    OuyaSDK.OuyaJava.JavaSetResolution("1280x720");

    Which calls into Java with:
    ajc.CallStatic("setResolution", resolutionId);

    And now you are in OuyaUnityPlugin.java:

    (this part might be different than usual)

    public static void setResolution(String resolutionId)
    {
    if (null == IOuyaActivity.GetUnityPlayer())
    {
    Log.i("Unity", "IOuyaActivity.GetUnityPlayer() is null");
    return;
    }
    if (resolutionId.equals("640x480"))
    {
    changeResolution(640, 480);
    }
    else if (resolutionId.equals("1280x720"))
    {
    changeResolution(1280, 720);
    }
    else if (resolutionId.equals("1920x1080"))
    {
    changeResolution(1920, 1080);
    }
    }

    And then I was playing around with setting the scale:

    private static void changeResolution(final int width, final int height) {
    if (null != IOuyaActivity.GetLayout()) {
    IOuyaActivity.GetActivity().runOnUiThread(new Runnable() {
    public void run() {

    WindowManager.LayoutParams params = IOuyaActivity.GetActivity().getWindow().getAttributes();
    params.width = width;
    params.height = height;
    IOuyaActivity.GetActivity().getWindow().setAttributes(params);


    //Log.i("Unity", "IOuyaActivity.GetLayout().layout(0, 0, width, height);");
    //IOuyaActivity.GetLayout().getLayoutParams().width = width;
    //IOuyaActivity.GetLayout().getLayoutParams().height = height;
    //IOuyaActivity.GetLayout().requestLayout();

    if (null != IOuyaActivity.GetView()) {
    IOuyaActivity.GetView().setScaleX(1920.0f / (float)(width));
    IOuyaActivity.GetView().setScaleY(1080.0f / (float)(height));
    }
    }
    });
    }
    }

  • rhellikrhellik Posts: 28Member
    Hm, why do you need to do the Java resize? Only for the touchpad input? Or are there other benefits? My game runs fine changing resolutions without the Java call.
  • tgraupmanntgraupmann Posts: 2,546Administrator, Team OUYA
    I wanted it to resize without having to hack the cursor mouse position and have the GUI line up. So buttons, GUI, and NGUI are clickable regardless of resolution.
Sign In or Register to comment.