Search Unity

Does UWP handle frames differently?

Discussion in 'Windows' started by Marscaleb, Jan 26, 2020.

  1. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    1,037
    I am trying to track down a bug where when my game first starts, it freezes momentarily as it performs a screen wipe, ruining the wipe effect (which is timed with the music, so it is really noticeable.) I do not see this happen when I test it within the editor, but it does happen when I run the game on my xbox.

    I thought the problem might be that the game was freezing for just a moment because it is loading the texture I am drawing on the screen to produce the wipe. I dropped a copy of this texture into my scene just to make sure the system pre-loads it, but it still has this problem. So maybe it still takes half a second to actually load it into the right part of its memory or something. So I thought: why not add some code to the wipe effect so that it just waits one frame after it loads the texture, that way if it is taking just an extra moment to load the texture, it won't actually start the wipe until the next time update is called. Thus if it takes a moment to load the texture, the wipe will start after this happens.

    But when I went through my code, I found that I was already doing this.

    The process works like this: I have code that gets called somewhere within the update function, which looks something like this:
    Code (CSharp):
    1. SetWipeType(WipeType.IrisCircle);
    2. StartWipeIn();
    SetWipeType will tell the script to load the requisite textures and set a few other variables. StartWipeIn actually looks like this:
    Code (CSharp):
    1. public void StartWipeIn() {
    2.         StartCoroutine(StartWipeInNextFrame());
    3.     }
    4.    
    5.     IEnumerator StartWipeInNextFrame() {
    6.         yield return null;
    7.         if (CurrentWipe != WipeType.MapWipe)
    8.             bScreenWipeActive = true;
    9.         bScreenWipedOut = false;
    10.         wipeTimer = 0;
    11.         bWipingIn = true;
    12.         GM.PlayMusic();
    13.     }
    So I'm wondering if using that IEnumerator with the yield return isn't going to actually execute on the next rendered frame. It seems to do this in the Editor, and I don't recall having this problem on Android when I was using that platform many years ago. But maybe UWP doesn't handle frames in quite the same way?
    Is it possible that this code above actually won't execute on the next rendered frame, thus it tries to execute while the game is still lagging behind for a moment as it loads data?

    I'm just spit-balling here; I can't figure out why this would happen.

    The game opens on a scene for the title screen, and initially has a splash screen drawn by the HUD to cover the screen. When the player presses a button I start a wipe. When the wipe finishes that splash screen stops being drawn and the wipe-in process automatically starts, using the code above. But the game stutters a bit on this wipe-in. It doesn't usually have problems when the game has been running a while, just for that first run when the game first turns on. Hell, even if I return to home and re-launch the game, it only has the slightest of stuttering. But if I turn on the console and launch the game (or upload a new build and launch the game) it will balk on that wipe-in, usually with my screen remaining completely black (from the wipe-out having just finished) while I hear the music playing, and then the screen suddenly appears because it balked for nearly the full second the wipe lasts.
     
  2. timke

    timke

    Joined:
    Nov 30, 2017
    Posts:
    408
    Hey,

    So the short answer to your question is: Yes, the UWP implementation in Unity is very different from the Editor and Windows Standalone player, similar to iOS and Android. Also, UWP is built with IL2CPP whereas the Editor (by default) uses Mono. These can cause subtle differences in runtime behavior, but I don't think that's necessarily the case here.

    I think your original assessment of the problem is correct: the texture isn't loading into memory before you attempt to use it in your wipe effect, causing the hiccup (for some reason).

    You mentioned "console" which I'm assuming means you're trying to run on Xbox One, correct? Does the problem occur if you build/run your UWP app on Windows? My guess is the lag has to do with running on an Xbox rather that UWP, but if the issue also occurs with UWP on Desktop then there could be a Unity bug here.

    Also try "manually" loading the texture asses, e.g. using AssetBundle.LoadAssetAsync() to see if that makes a difference.

    A couple other questions:
    - What version of Unity are you using?
    - Are you using the "new" Asset Pipeline?
     
    Last edited: Jan 27, 2020
  3. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    1,037
    Yes, this is an issue running it on Xbox One. I haven't been compiling test builds for the PC yet; it doesn't have the same fun "charm" as seeing my game run on on a console.
    I will look into testing it on a PC this week and see what happens.

    That's new to me, but I also recently learned that I shouldn't be using resources.load as much as I have, so I'll look into that hopefully this month, since I need to look into a different method to load assets anyway. (And yes, in my current version that textures loads via resources.load)

    Looks like 2019.2.3f1. Not the most recent, but still fairly recent.
    And I'm not sure what the assets pipelines are, so I'm probably not using the new one, since I'm working basically the same way I did when I was using Unity 4.
     
  4. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    1,037
    Okay, so I'm trying to test this with other platforms.
    If I compile this game as a PC Standalone, it does not have this problem.
    But I'm having problems testing the UWP. How do I make a "standalone" UWP app that I could run on a different computer? I've been compiling the UWP stuff on an old laptop that runs Windows 10. (My dev PC runs windows 7 because I have important programs that won't run in Windows 10) It's not exactly up to par. When I try to run my game on it, every new scene any many significant events cause it to hang for several seconds anyway, so I'd like to make a program I can put on a drive and take to a friend's house to test it with.

    That being said, when I switched Visual Studio to have the green play arrow target my local machine instead of my remote machine, I did notice something telling. In this starting sequence, it was running the opening wipe just fine for almost a second, and then it froze for several seconds while the wipe was only part-way through.
    This is suggesting that whatever is causing my game to hang isn't being caused by the wipe loading a graphic, but by something else happening while the game is just starting. If so, then on a faster system like the Xbox it gets triggered sooner. (this is just a best guess, at least.)
    However, there is nothing else that my code is running. The opening splash screen and the wipe are all just for show, running through the GUI. Everything running on my title screen already exists and is running its code; there is no reason for the game to hang at this point.
    Not unless Unity is running its own code because this was the first time any user input was ever given, or it was the first time a sound started playing, or some other early-game code that the engine doesn't call right away.
     
    Last edited: Feb 4, 2020
  5. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,679
    The UWP build that you run on xbox can literally run on PC too. Just instead of deploying to Xbox (by typing Xbox IP address), you can deploy to Local Machine or type in a Windows 10 machine IP. Keep in mind that the Windows 10 machine has to have developer mode and "Device discovery" enabled in "developer settings".

    If you want to put it on an USB stick, you can create "AppX package" in Visual Studio by going into Project -> Store -> Create App Package. That will produce a folder with all files needed to install it on another machine.

    Did you try using the profiler to figure out what the hang actually is?

    Lastly, this is all very hard to imagine without seeing what's happening. Could you capture some videos to show what should be happening and what's actually happening?

    EDIT - a couple of other thoughts:

    1. Since the issue happens in UWP build on your laptop - does it happen in non-UWP build on your laptop?
    2. When you're deploying the UWP application, which configuration are you using (debug/release/master)? If you're using debug, try switching to release.
    3. I can't imagine Xbox being faster than your laptop, unless your laptop is 2008 or older. The CPU in the Xbox One is really really really slow.
     
  6. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    1,037
    Okay, here's a video showing the effect and what happens when I run it on my Xbox.
    I want to mention that the background and music are placeholder content, but the final version would operate in the same fashion.


    As seen in the video, it stalls when it is supposed to be running the iris wipe. Sometimes I've seen it stall while the wipe is already going, although I didn't manage to capture this on video. As I said it did that on my laptop (And I checked the specs, its processor is slightly slower than the Xbox, plus only has two cores, and has to try to chug Windows 10 at the same time.)
    When I ran the standalone PC version I noticed it only stalling for one or two frames in the middle of the wipe, but usually it runs without any problems.
    It tends to be fine on its second run; if I just quit the game and come back in it will often run smoothly. But on its first run, when I've first copied the latest version, it always hangs like this.

    I have not tried using the profiler to figure out what the hang is; I am unfamiliar with that. How do I use it?
     
  7. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,679
    Here's how to use profiler: https://docs.unity3d.com/Manual/profiler-profiling-applications.html

    Keep in mind that profiling UWP applications cannot be done on a machine where the app is running on (that is, if you both run Unity editor and the UWP app on your laptop). You'll have to run Unity on your main PC and the UWP app on your laptop or the Xbox.

    Regarding my 1) and 2) points - did you check them? Lastly, did you try running the UWP app without a debugger attached? Debugger can cause random freezes in the process as DLLs are loaded/unloaded.
     
  8. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    1,037
    Sorry for the long delay; I had some other projects facing deadlines I had to take care of. Didn't get time earlier to really try out the things you mentioned.
    I just tried running the standalone build on the laptop. It hung up in that same spot for a good 30 seconds, fairly similar to how it handled the UWP test build on a local machine.
    I've been using "Master" builds.

    I'm trying to use the profiler but I'm having a hard to understanding what I'm looking at and how it is relevant.
    I think something called Mono.JIT is taking a big chunk of processing resources at that time, but this wasn't from looking at the profiler while running my game in the editor, trying to understand what I'm looking at.
     
    Last edited: Mar 1, 2020