Unity Community


Page 1 of 5 123 ... LastLast
Results 1 to 20 of 91

  1. Location
    Paris
    Posts
    3,730

    Coroutines are badass

    Just wanted to emphasize that well-established fact :

    Coroutines are awesome for performance optimization

    I turned to a coroutine an old Update() function that just checked if a fixed float was superior to Time.time, in which case it would turn a boolean to true. And it made me gain 5 fps.

    Yeah, that much. The coroutine removed that checkout by randomly changing the boolean every 1 to 4 seconds.

    Now I can imagine how my actual fps would benefit from turning every looped methods into coroutines ^^


  2. Location
    NE Ohio, USA
    Posts
    7,173

    Re: Coroutines are badass

    If you're doing anything where you check for time differences, then coroutines are great. Much better than anything you could do with Update().

    You can't use them for everything you'd do in Update(), though, because you only get a performance benefit if the processing happens less than it would, if it happened every frame. So the greater the number you input to WaitForSeconds, the less responsive the game is going to be. It's a nice way to optimize, though. See if everything can run at a smooth framerate in Update(), and if not, start putting what's less important in coroutines, and keep kicking the values you use for WaitForSeconds up until the game is playable.


  3. Location
    Paris
    Posts
    3,730
    That's cool advices Jessy, thanks.

    I'll see what would benefit and what would not, but except the input detection & movements methods, I guess nothing else has to be checked on every single frame (for basic behaviours I mean).

    In fact I'm already running at 40 fps on 3GS, but I feel a lot could be improved via coroutines

    On the other hand, one thing that annoyed me at first with checkup coroutines was that while(true) statement.

    Apple clearly stated that every dev should avoid loops and Polling in general.

    Quote Originally Posted by Apple
    Use Event-Based Handlers

    All modern Mac OS X applications should be using the Cocoa event system or Carbon Event Manager. (Similarly, iPhone applications must use the touch-based event system provided by the UIKit framework.) Your application should never retrieve events by polling the system. Doing so is highly inefficient. In fact, when there are no events to process, polling code is a 100 percent waste of CPU time. The modern event-based APIs are designed to provide the following benefits:

    They make your program more responsive to the user.
    They reduce your application’s CPU usage.
    They minimize your application’s working set—the number of code pages loaded in memory at any given time.
    They allow the system to manage power aggressively.
    Besides user events, you should avoid polling in other situations as well. Threads in Mac OS X and iPhone OS use run loops to provide on-demand responses to timers, network events, and other incoming data. Many frameworks also use an asynchronous programming model for certain tasks, notifying a designated handler function or method when the task completes.

    Here.

    And more there.


  4. Location
    Zürich, Switzerland
    Posts
    26,572
    40 on the 3GS isn't all that great ... thats at very best 15 - 20 on the 1st generation devices and potentially the iphone 3G


    As for the event handlers: you aren't working with UIKit, so they are of no importance.
    Though what I would recommend you to do is not using any time difference measures. use yield and wait till the time has passed point


  5. Location
    Paris
    Posts
    3,730
    Well, I guess 40 fps is still pretty good for a start before any deep optimizing process, considering the high number of bones and keyframes of my chars (82 bones total, 2000 x 2 keyframes, 1024 textures), plus all the visual effects, custom HUD, physics and higly detailed background

    Still optimizable though, but for what I see on my handheld, it's already appearing very smooth and responsive

    And I will abuse of yield, for sure


  6. Location
    Zürich, Switzerland
    Posts
    26,572
    Thats no wonder, your device is up to 4 times faster than the 3G and older ...
    So yes you are still looking forward to a lot of optimization or cut down of your userbase to more or less the 3GS owners

    sounds especially like you will have to work on the memory consumption of your app to make it run at all


  7. Location
    Paris
    Posts
    3,730
    That's actually the tweaking I found to be efficient, yes, cutting textures by an half to make it run on 3G ^^


  8. Location
    NE Ohio, USA
    Posts
    7,173
    Quote Originally Posted by n0mad
    That's actually the tweaking I found to be efficient, yes, cutting textures by an half to make it run on 3G ^^
    For which Unity is awesome, because you can just change Import Settings instead of actually importing resized graphics.


  9. Location
    Paris
    Posts
    3,730
    Quote Originally Posted by Jessy
    Quote Originally Posted by n0mad
    That's actually the tweaking I found to be efficient, yes, cutting textures by an half to make it run on 3G ^^
    For which Unity is awesome, because you can just change Import Settings instead of actually importing resized graphics.
    Yup I like that feature, but it's even more awesome with Texture2D.PackTextures() where you can just tell what target size you want


  10. Location
    Paris
    Posts
    3,730
    By the way, what is the unit reference of "frametime" in the profiler ?
    is it the fps ?


    here is one from an actual build :

    Code:  
    1. iPhone Unity internal profiler stats:
    2.  
    3. cpu-player>    min: 17.4   max: 29.3   avg: 24.4
    4. cpu-ogles-drv> min:  3.0   max:  5.7   avg:  3.7
    5. cpu-present>   min:  0.5   max:  1.8   avg:  0.6
    6. frametime>     min: 25.2   max: 43.0   avg: 33.3
    7. draw-call #>   min: 5   max: 5   avg: 5
    8. tris #>        min: 4220   max: 4220   avg: 4220
    9. verts #>       min: 6196   max: 6196   avg: 6196
    10. player-detail> physx:  0.4 animation: 11.3 skinning:  8.3 render:  1.7 fixed-update-count: 1 .. 2
    11. mono-scripts>  update:  2.1   fixedUpdate:  0.4 coroutines:  0.0
    12. mono-memory>   used heap: 2064384 allocated heap: 3960832
    13. ----------------------------------------


  11. Location
    Zürich, Switzerland
    Posts
    26,572
    all times are milliseconds.


  12. Location
    Paris
    Posts
    3,730


  13. Location
    Zombieville, USA
    Posts
    808
    Your "used heap" there is pretty large. Does it go up every frame by chance? You may be performing memory allocations in your scripts every frame, which can lead to hiccups down the line due to frequent mono GC. In particular, coroutines can cause such allocations in some situations.


  14. Location
    Paris
    Posts
    3,730
    I found it to be that high on every frame, even if I don't have any clue of how much we should aim for in a reasonable way. It was that high even before the coroutine translation.

    I guess it's because of the huge animations, each char has a 8 MB animation (40 - 50 moves per character), and 4 x 1024 texture atlases (2 chars + 1 background + 1 HUD).

    When I will reach the deep optimization process, I'll cut characters texture size by an half for sure.
    But I feel like I can't help but have a huge Animation allocation for this type of game :/



    edit @ Tagged : Don't worry dude, you're not stealing anything, I would be happy to launch (yet another) general performance thread


  15. Location
    Brisbane, Australia
    Posts
    62
    Quote Originally Posted by PirateNinjaAlliance
    Your "used heap" there is pretty large. Does it go up every frame by chance? You may be performing memory allocations in your scripts every frame, which can lead to hiccups down the line due to frequent mono GC. In particular, coroutines can cause such allocations in some situations.
    Just in regards to this, I've notice the used heap in my game going up until the end of the background mp3 music, once that loops over and starts again the used heap drops right back down. This happens in sync with the music every time, is this normal? Or should I be looking through the code for culprits?

    Apologies for the thread stealing


  16. Location
    Zombieville, USA
    Posts
    808
    Compressed audio doesn't add to your mono heap, so if its going up in sync with your music that's just a coincidence. The only thing that should contribute to that particular chunk of memory is allocations from script - assets like textures, sounds and animations are not represented there. The actual size of the heap isn't really that big of a concern by itself as long as its size is relatively steady, but if its rising every frame you've got some kind of allocation happening in your update(s). This will eventually cause mono garbage collection to trigger, which can make your framerate stutter unpleasantly for a second or two. The severity and frequency of mono GC's effect on your framerate can vary wildly - its usually not a showstopper even if GC is running pretty frequently, but its best to avoid it for ideal performance. There's generally no reason why you'd ever have to perform allocations every frame, so its quite avoidable if you keep an eye on it.


  17. Location
    NE Ohio, USA
    Posts
    7,173
    Quote Originally Posted by PirateNinjaAlliance
    if its rising every frame you've got some kind of allocation happening in your update(s)...

    There's generally no reason why you'd ever have to perform allocations every frame, so its quite avoidable if you keep an eye on it.
    Can you tell me what might cause that to happen? For instance, would this code be improved by declaring the variables outside of Update?

    Code:  
    1. void Update ()
    2. {   
    3.     int touchCount = iPhoneInput.touchCount;
    4.     bool moving = false;
    5.     bool looking = false;
    6. }

    I have been declaring variables inside of functions when they won't need to be used outside of the functions, but if that's allocating memory for a new variable each time, I will stop doing that immediately.


  18. Location
    Colorado - USA
    Posts
    408
    Can anyone tell me if InvokeRepeating has the same optimization benefit as using a coroutine with yield discussed here? I find it to be a cleaner approach than using a coroutine with a while() loop.


  19. Location
    Zürich, Switzerland
    Posts
    26,572
    Well benefit is that invokerepeating gets a new clean memory each time again, no remainder from the last run.
    drawback is that it also has to reserve that again on each call.


  20. Location
    Zombieville, USA
    Posts
    808
    Quote Originally Posted by Jessy
    Can you tell me what might cause that to happen?
    I know for sure that checking an animation state's values, like in the following script...

    Code:  
    1. function Update () {
    2.      if (animation["idle"].weight == 1) {
    3.            // do stuff
    4.      }
    5. }

    ... will allocate every frame, whereas...

    Code:  
    1. var idle = animation["idle"];
    2.  
    3. function Update () {
    4.      if (idle.weight == 1) {
    5.           // do stuff
    6.      }
    7. }

    ... does not. I've also noticed that this use of co-routines causes allocations every frame, whether it someCondition is true or not...

    Code:  
    1. function Update () {
    2.      someFunction();
    3. }
    4.  
    5. function someFunction () {
    6.      if (someCondition) {
    7.          yield WaitForSeconds (1);
    8.          // do stuff
    9.      }
    10. }

    Meanwhile, this does not, even though it is identical in function.

    Code:  
    1. function Update () {
    2.      someFunction();
    3. }
    4.  
    5. function someFunction () {
    6.      if (someCondition) {
    7.           yetAnotherFunction();
    8.      }
    9. }
    10.  
    11. function yetAnotherFunction () {
    12.      yield WaitForSeconds (1);
    13.      // do stuff
    14. }

    I've learned these "rules" by trial and error, and watching my mono memory closely whenever I'm running the profiler. I'm sure there are other things to avoid as well - as a general rule, I always cache any reference to any component in a variable, and never really never declare temp variables inside a function at all out of paranoia.

Page 1 of 5 123 ... LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •