Search Unity

Game Stutters after adding a Singleton :/

Discussion in 'Scripting' started by Necrobata, Jun 10, 2019.

  1. Necrobata

    Necrobata

    Joined:
    Dec 12, 2018
    Posts:
    12
    Hey guys! ive been trying to sort this issue for a week now. Im working on a mobile game and it used to run really well on my cellphone until i added 2 scenes meant for ingame ads (for self promote a toy made for the company i work with) and i also added a singleton object to keep track of your max Score and thats it.

    When i was starting to program it, i remember my parallax and my player (this is a sidescroller) stuttered until i learned that movement and visual updates should go on FixedUpdate, so i placed all of these in here and voilá, i unshitted the fan, it ran amazingly well.

    But now its just like that stutter is back again :/

    So, the code inside my PersistentManager Script goes like this:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PersistentManagerScript : MonoBehaviour
    6. {
    7.     public static PersistentManagerScript Instance { get; private set; }
    8.  
    9.     public int Score;
    10.  
    11.     private void Awake()
    12.     {
    13.         if (Instance == null)
    14.         {
    15.             Instance = this;
    16.             DontDestroyOnLoad(gameObject);
    17.         }
    18.         else
    19.         {
    20.             Destroy(gameObject);
    21.         }
    22.     }
    23. }
    At the end of the level theres a small script that triggers a timer to instantiate an object that covers the screen as a courtain and when it goes totally black, switching scenes by then. Thats one of the main changes i made, i added around 3 or 4 of those just to make a good seamless UI throughout the game.

    Then i read that my game might stutter for several causes. It started by having around 40-70fps and the profiler showed a memory usage of 0.56gb. Then i acted.

    1- I disabled Vsync and the framerate went up to 400-700 frames.
    2- I saw that a good piece of memory went on animations, i was able to lower that load by eliminating frames off my objects, around 30% lesser frames. (Build went from 60mb to 53mb or so)
    3-I cleaned up every script that was using the Update method to make comparisons every frame. For example, the persistent manager was counting the score every frame, i removed that code and now the check is only made at the end of the level. There are no lists, no "for x, do y" cycles.
    4- I revised my level design. the level consisted in 5 "isles" separated by water, when you jump to a new section, theres a trigger that destroys the last one you were and instantiates the next, so you never have more than 2 tilegrids. Also erased all the tiles that werent visible when you run the game.
    5- All of the art was made in pixelart and scaled inside the game, not sure if this is good or bad.
    6- I had this huge 4000x1200 image as a background. I severed that to fit only the camera view, then programed it to follow the camera around. Not sure if worked.

    After all these changes, the Profiler gives me these at CPU usage:

    EditorLoop: 63.2% (sometimes is over 90%)
    PlayerLoop: 29.6%
    Profiler.CollectEditorStats: 6.4%

    In the memory Tab:

    Total Allocated memory: 1.18Gb (Unity uses 0.98, mono 15.8mb)
    Reserved total: 1.84Gb (unity 1.57.. etc etc etc )
    Texture memory: 410mb.
    The rest are small values compared to these two.

    So, this is it. I consider myself a rookie polishing himself at my first attempt for a game. I could use an insight if i should read anything regarding a possible solution. If anyone have gone through this id appreciate some light :)

    Have a great day!
     
  2. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    My only real advice is that, to the greatest degree possible, you should really avoid instantiating or destroying GameObjects or Components while mid-scene. For simple singletons like this, create them immediately on scene load instead of waiting. For more complex objects, like those with sprites/meshes, figure out the maximum number of any given entity you'll need to have exist simultaneously, then generate, disable, and pool those right off the bat when the scene is being loaded. When you need one of them, request an instance, enable it, use it, then when it's no longer needed, disable and re-add it to the pool to be used again later.

    You trade a little extra memory for getting rid of stutters like that.

    In situations where you can't really spend the memory all of the time though, you can at least pre-load the assets you need at a preset time just before you actually need them, so you can spread the instantiations over many frames instead of all-at-once. An example might be a scene where you spawn a bunch of enemies to attack the player, but you don't want to have them all pooled all of the time since it's a one-time event. Spawning 30 objects at once can be harsh, but doing 1 every few frames leading up to the event can help spread out the damage, so to speak, as can destroying one every few frames as well.

    There are plenty of guides around on making GameObject pools if you decide to go that route- you can even just tear one out of LordOfDuct's Spacepuppy Framework (it's up on GitHub) if you want a complete solution, though it'd have to be edited to remove some dependencies. The whole framework would probably be overkill for a completed project you're just trying to optimize though.

    Just some thoughts. Good Luck. =)
     
    Last edited: Jun 10, 2019
  3. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    When possible, always do an actual build vs editor run to test how it might perform as the final product (helps get rid of editor overhead)

    Then, if you are seeing issues, use the profiler. There is also the memory and physics profiler as well as the deep profiler. All these can help you get to the root of the issue.
     
  4. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,638
    Your PersistentManager isn't really doing anything so it's hard to imagine that's causing the stutter.

    Using the profiler you should be able to get a break-down of all the things that are going on during the player loop and the % of time that each one is taking-up.

    Also since the editor loop is so high (percentage wise), you might want to try to profile on a build.
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    Mind you I've moved onto version 3, and I've removed Singleton all together.

    I do a pure "services" based design now.
     
    DonLoquacious likes this.
  6. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    @lordofduct Oh nice, I've moved on to services as well- I'll have to take a look at it. =)
     
  7. Necrobata

    Necrobata

    Joined:
    Dec 12, 2018
    Posts:
    12
    I appreciate your reply! im gonna read about the object pooling, i swore the most memory-wise call was to instantiate what you needed and destroy what you dont...

    I quite dont get what you call as pre-load something. I mean, if im on a scene and i go to another, things just... load right? how do you pre load? whats the difference?

    I dont know how to add frameworks to my project yet :(

    Thanks for your reply!
     
  8. Necrobata

    Necrobata

    Joined:
    Dec 12, 2018
    Posts:
    12
    The game runs smooth and pretty on my computer, but stutters in my cellphone, its not unplayable, but its a downgrade from what it was. I really cant understand how i hit 700fps on my pc but the game sill stutters :I
     
  9. Necrobata

    Necrobata

    Joined:
    Dec 12, 2018
    Posts:
    12
    After i made the post i realized the Persistent isnt doing anything but hold a single int. I think i can use PlayerPrefs instead and eliminate that object throughout the whole level. Adding the Persistent Manager was the only actual change i made to the scene before the stutters started.

    I have no idea whats the Editor Loop doing, neither i can break it down because it doesnt have that dropdown arrow to see whats running. Is there a way to check which scripts are running heavy on my build?
     
  10. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    It's a trade-off, a little memory for less processing at critical moments. And no, scenes don't usually have absolutely everything in them they're going to need (although I suppose they could)- when an enemy spawns, you usually create it from a prefab. You're instantiating an object into a scene that wasn't loaded with the scene itself. That instantiation is expensive, and can cause some lag. If you instantiate it earlier in the scene / on scene load instead, even though you don't need that enemy yet (disabled and waiting in a "pool"), you can do the loading when it matters less and no one's going to notice the stuttering. During a loading screen, for instance.
     
  11. Necrobata

    Necrobata

    Joined:
    Dec 12, 2018
    Posts:
    12
    Services i know its water, internet and electricity.

    I shall also do a research in what the hell are services xD
     
  12. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    You can use the mobile profiler to test builds running on an Android device. This should give you an idea of where your bottlenecks are.
    If you are on iOS, there may be something similar in xCode.
     
  13. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,638
    I don't think that would help at all. Player Prefs writes and reads from file, which is hundreds of times slower than RAM. You'd be replacing something trivially tiny with something that is cumbersome. I suppose you could try it, though.

    I still don't think that script is the cause of your problems.
     
  14. Necrobata

    Necrobata

    Joined:
    Dec 12, 2018
    Posts:
    12
    Holy :/ havent done anything yet, been working on some ads for it, bosses orders :/

    Im gonna sit right now and try some of the fixes posted in here!

    I remember once, my animations were running with delay. A 50ms-so delay that drove me crazy! I literally didnt do anything to cause it, i just made a whole new level, rebuild everything exactly the same. And it fixed the issue :I

    I might even think about re-doing the whole level again which isnt much of a problem.

    I appreciate the replies :)
     
  15. Necrobata

    Necrobata

    Joined:
    Dec 12, 2018
    Posts:
    12
    Hey Guys i trully appreciate your help :) i thank each and every one that suggested fixes :)