Search Unity

Better Loading Indicator in WebGL

Discussion in 'Web' started by BabilinApps, Jun 22, 2015.

  1. ivabibliocad

    ivabibliocad

    Joined:
    Jan 11, 2014
    Posts:
    80
    IT WORKED but...
    I now understand that when I tried this, it was done in conjunction with the template found at the begging of this topic. Because, before the loading problem, my main goal was to be able to show the loading progress as a percentage.
    So The ".htaccess" works perfectly. But going back to my main goal, it doesn't work with that percentage loader. I understand that's out of your scope and I'll have to learn more about it or talk to those guys for the complete solution.
    Like always thanks for the great and clear help!!
     
    Last edited: Sep 23, 2016
  2. JakeOfSpades

    JakeOfSpades

    Joined:
    Aug 22, 2015
    Posts:
    44
    This is awesome, thank you so much!
     
  3. _Radagan

    _Radagan

    Joined:
    May 16, 2014
    Posts:
    38
    Thank you! This should ship with Unity!
     
  4. ponx

    ponx

    Joined:
    Sep 13, 2010
    Posts:
    45
    hi Alex,
    apparently for me it was b) , the build is no longer working, using the .htaccess you posted above, failing with "unknown compression method in UnityLoader.js"
    However using the previous .htaccess (from Unity 5.3) my build is generally working, and i also made sure that the hosting server responded with "Content-Encoding: gzip" in the HTTP Response header when i download Release/webgl.jsgz
    Despite of that i am still getting the warning from UnityLoader.js in the browser Console: "Decompressed Release/mygame.datagz in 225ms. You can remove this delay if you configure your web server to host files using gzip compression".
    What can i do? I hope you can help, thanks for your efforts!
     
    Last edited: Nov 20, 2016
  5. SimDevs

    SimDevs

    Joined:
    Jan 7, 2014
    Posts:
    25
    This was the missing part for me - that could not find anywhere on the web !!!
    Wasted almost all day by trying to fix that progress bar issue and compression warning!

    Thanks for the info!
     
  6. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    If you wanted a complex but low bandwidth progress animation would a gif or video be best and could you control the speed/progression of the animation so it relates to the loading speed of your game?
     
  7. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Hello ponx.

    The server should append Content-Encoding: gzip header for Release/webgl.js if and only if the access is redirected to Release/webgl.jsgz. The server should not append Content-Encoding: gzip header for Release/webgl.jsgz.

    Depending on your server configuration mod_rewrite and mod_mime modules might be unavailable, which will make the old .htaccess to fail.

    Other reasons why .htaccess may cause incorrect results:
    - you have another .htaccess file somewhere closer to the root, which introduces conflicting configuration (configuration is inherited by subfolders).
    - server appends Content-Encoding: gzip header for all the *gz files. This configuration is not default, however some hosting providers use it.
    - server has static gzip compression enabled, in which case you might end up with a double-compressed file.
    - your server configuration is not default.

    To make sure, post a link to your build (here or privately).
     
  8. ponx

    ponx

    Joined:
    Sep 13, 2010
    Posts:
    45
    Alex, thanks a ton for willing to look into this. Indeed i get Encoding:gzip for every single file in my Release folder. I made sure there are no other .htaccess files interfering in parent directories. Here's the link to my project:
    http://realisticaquarium.com/client/webgl
    I'm pretty lost here, e.g. i haven't understood when and why access will be redirected to different files. The only .js file in my exported Project is UnityLoader.js.
    Best greetings, ponx
     
  9. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Hello ponx.

    I have checked on the link and it appears that you have static gzip compression enabled on your server. I used the following hints to determine this:
    - The files are served with Content-Encoding: gzip header even though you don't have .htaccess appending that header.
    - Appended Etag:"db4d95-541e44a08e880-gzip" etc. headers indicate that compression has been performed by the server.

    When static compression is enabled, server automatically serves your files compressed with all the necessary headers appended.

    Bad news:
    Standard .htaccess can not work in this server setup (unless you have access to the httpd.conf where you can disable static compression).

    Good news:
    You don't need to use .htaccess in such server setup in the first place, because your server will perform compression for you. Instead you may just create an uncompressed build (use Compression Format: Disabled in the Publishing Settings). Even though you will upload and store uncompressed content (without *gz suffixes) on your server, it will still be served compressed with all the necessary headers automatically appended, as you server is already set up to do this for all the served files. Your loading indicator should also work just fine.

    Drawback:
    If the client does not support gzip compression or does not provide Accept-encoding: gzip header, then the content will be served uncompressed, which will result in significantly slower startup. Even though all modern browsers support gzip, the issue might still eventually occur due to intermediate proxy servers not accepting gzip (the header might also be incorrectly stripped by antivirus software). In case of standard server setup .htaccess would cause 404 in such case due to the RewriteCond %{HTTP:Accept-encoding} gzip and UnityLoader would fallback to the JavaScript decompression, which is still much faster than downloading uncompressed content. Note that this situation is quite rare (around 1%) and can be ignored.
     
    Last edited: Nov 24, 2016
  10. ponx

    ponx

    Joined:
    Sep 13, 2010
    Posts:
    45
    Thanks a million for your help and your very good explanations, Alex! Thats good news, all in all! I'll switch to Unity 5.5 as soon as possible to make use of the Publishing settings (5.4.2 doesn't include it yet i figured). However i just unpacked the contents of a regular compressed build, uploaded it and the progress bar worked just as you said!
    I'm not sure if i should ask my web hoster to disable static compression for me (it was rather tedious to make them enable gzip in the first place :) ). So good to know there's a fallback option! Thanks again!
     
  11. DaveLevi

    DaveLevi

    Joined:
    Dec 6, 2016
    Posts:
    3
    This thread was very helpful, thanks!

    I've been playing around with getting this to work with a unity app hosted on S3. It seems to be pretty much working now, so thought I'd share what I did:

    1. Turned Data Caching off in the unity build settings

    2. Renamed the Release/XXXgz files to just Release/XXX before uploading them to S3

    3. For each of the Release/XXX files on S3, added a metadata tag of Content-Encoding:gzip

    4. Also changed the Content-Type for the two Release/*.js files to application/javascript

    I'm using the CustomProgress template from BabilinApps. I now get the download bar, and I see the correct progress numbers being updated as the app downloads (bytes downloaded / bytes total). BTW, also using Unity5.5.
     
  12. dforstmaier

    dforstmaier

    Joined:
    Oct 5, 2016
    Posts:
    13
    Just wanted to add, that we had an issue with gzip encoding and the header. Although everything is setup fine, the client still downloaded the fully unpacked file - not the gzip. The header also included "Transfer-Encoding:chunked". Both Apache and nginx seemed to failed. But our actual problem was: the antivirus program.

    Our antivirus program activated something like "Check application specific protocol" which internally somewhat mistrusts every zipped file. Deactivating this option solved our problem.
     
  13. screenname_taken

    screenname_taken

    Joined:
    Apr 8, 2013
    Posts:
    663
    Guys, does anyone have the loading bar script that was linked in the first post?
    Link is dead.
     
  14. DaveLevi

    DaveLevi

    Joined:
    Dec 6, 2016
    Posts:
    3
    Just noticed this, here it is.
     

    Attached Files:

  15. screenname_taken

    screenname_taken

    Joined:
    Apr 8, 2013
    Posts:
    663
  16. ATMEthan

    ATMEthan

    Joined:
    Dec 27, 2012
    Posts:
    54
    Can anyone confirm this is working on Unity 5.6.0f3? I'm trying to implement this and my web GL export just sits at full bar and displays "Loading..."

    This is what I did:
    1. Took the contents of the zip from two posts above and place them in: "C:\Program Files\Unity\Editor\Data\PlaybackEngines\webglsupport\BuildTools\WebGLTemplates"
    2. Next downloaded the last UnityProgress.js posted (Post #21 I think) and replaced the old UnityProgress.js with the newer one.
    3. In unity, I chose the "CustomProgress" template under Resolution and Presentation.
    4. I built... and I get a frozen webpage as described above.

    I'm using firefox and chrome (with extension "web server for chrome") to test my builds.

    What am I missing? Or Where did I go wrong?

    Thanks for the help Community!
    -E
     
  17. sama-van

    sama-van

    Joined:
    Jun 2, 2009
    Posts:
    1,734
    Same here....
    The bar is frozen and doesn't load anything...
    Written %UNITY_WEBGL_LOADER_GLUE% to the top left... o_O...
     
  18. JeffersonReis

    JeffersonReis

    Joined:
    Sep 7, 2014
    Posts:
    5
  19. brunokeith

    brunokeith

    Joined:
    Oct 29, 2013
    Posts:
    6
    The Unity 5.6 doesn't use the %UNITY_WEBGL_LOADER_GLUE% anymore. See https://forum.unity3d.com/threads/new-unity-webgl-embedding-api-white-paper.430909/
     
  20. FriesB_DAEStudios

    FriesB_DAEStudios

    Joined:
    Jul 1, 2014
    Posts:
    1
    For the newest versions of Unity (5.6.x - 2017) I had to rewrite the file TemplateData/UnityLoader.js to this:

    Code (JavaScript):
    1. var loadingData = {};
    2. loadingData.progress = 0.0;
    3. loadingData.message = "";
    4.  
    5. loadingData.SetProgress = function (progress)
    6. {
    7.     if (loadingData.progress < progress)
    8.     {
    9.         loadingData.progress = progress;
    10.     }
    11.     if (progress == 1)
    12.     {
    13.         loadingData.SetMessage("Preparing...");
    14.         document.getElementById("spinner").style.display = "inherit";
    15.         document.getElementById("bgBar").style.display = "none";
    16.         document.getElementById("progressBar").style.display = "none";
    17.     }
    18.     loadingData.Update();
    19. }
    20.  
    21. loadingData.SetMessage = function (message)
    22. {
    23.     loadingData.message = message;
    24.     loadingData.Update();
    25. }
    26.  
    27. loadingData.Update = function()
    28. {
    29.     var length = 200 * Math.min(loadingData.progress, 1);
    30.     bar = document.getElementById("progressBar");
    31.     createjs.Tween.removeTweens(bar);
    32.     createjs.Tween.get(bar).to({width: length}, 500, createjs.Ease.sineOut);
    33.     document.getElementById("loadingInfo").innerHTML = loadingData.message;
    34. }
    35.  
    36. loadingData.Clear = function()
    37. {
    38.     document.getElementById("loadingBox").style.display = "none";
    39. }
    40.  
    41. function UnityProgress(gameInstance, progress)
    42. {
    43.  
    44.   if (!gameInstance.Module)
    45.     return;
    46.   if (!gameInstance.progress)
    47.   {
    48.       //INITIALIZATION
    49.     gameInstance.progress = document.getElementById("loadingBox");
    50.  
    51.     createjs.CSSPlugin.install(createjs.Tween);
    52.     createjs.Ticker.setFPS(60);
    53.  
    54.   }
    55.   loadingData.progress  = progress;
    56.   loadingData.Update();
    57.  
    58.   if (progress == 1)
    59.   {
    60.         loadingData.SetMessage("Preparing...");
    61.         document.getElementById("spinner").style.display = "inherit";
    62.         document.getElementById("bgBar").style.display = "none";
    63.         document.getElementById("progressBar").style.display = "none";
    64.   }
    65.  
    66. }
    67.  
    68. //Called from Unity on Awake
    69. function FinishedLoading()
    70. {
    71.     loadingData.Clear();
    72.  
    73. }
    74.  
    The function FinishedLoading is called from Awake() in a script that's in the first loaded scene using Application.ExternalCall():

    Code (CSharp):
    1. private void Awake()
    2. {
    3.     Application.ExternalCall("FinishedLoading");
    4. }
     
    Last edited: Aug 22, 2017
    yuliyF likes this.
  21. jomirusergiu1

    jomirusergiu1

    Joined:
    Nov 4, 2017
    Posts:
    1
    Can anyone post a link with working template for 2017 version? thanks
     
  22. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    How would I add a pre-loading place holder like the play button on a video, where the user has to click to trigger the game to load?
     
  23. larku

    larku

    Joined:
    Mar 14, 2013
    Posts:
    1,422
    I am totally guessing here but, I expect you need to just add a html/css/what-not button which calls the:

    Code (CSharp):
    1.         var gameInstance = UnityLoader.instantiate("gameContainer", "%UNITY_WEBGL_BUILD_URL%", {
    2.             onProgress: UnityProgress
    3.         });

    part of the index.html.

    Could be wrong, but I can't see why that wouldn't work.
     
  24. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
    Here's some code I used to get this to work:
    Code (csharp):
    1. <div class="unitywebgl-container">
    2.    <div class="clicktoload" href="#" onclick="runUnityLoader();">
    3.        <div class="logo -middle">Click to Load</div>
    4.    </div>
    5.    <div class="logo -corner">WebGL</div>
    6.    <canvas class="emscripten canvas" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
    7. </div>
    8.  
    9. <script type='text/javascript'>
    10.    var Module = {
    11.        TOTAL_MEMORY: 20000000,
    12.        errorhandler: null,           // arguments: err, url, line. This function must return 'true' if the error is handled, otherwise 'false'
    13.        compatibilitycheck: null,
    14.        backgroundColor: "#F8F8F8",
    15.        splashStyle: "Light",
    16.        dataUrl: "{{ site.baseurl }}/Game.data",
    17.        codeUrl: "{{ site.baseurl }}/Game.js",
    18.        asmUrl: "{{ site.baseurl }}/Game.asm.js",
    19.        memUrl: "{{ site.baseurl }}/Game.mem",
    20.    };
    21.  
    22.    $(".clicktoload").click(function () {
    23.        $(".clicktoload").css("display", "none");
    24.    });
    25.  
    26.    function runUnityLoader() {
    27.        var script = document.createElement("script");
    28.        script.src = "{{ site.baseurl }}/Release/UnityLoader.js";
    29.        document.body.appendChild(script);
    30.    }
    31.  
    32.    // https://stackoverflow.com/questions/2190801/passing-parameters-to-javascript-files
    33.  
    34. </script>
    When clicked, everything inside "clicktoload" class gets hidden, and "runUnityLoader" creates the actual unity game which will start to load (you'll notice the browser hang for a second).

    CSS:
    Code (csharp):
    1.  
    2. .unitywebgl-container {
    3.    position: relative;
    4. }
    5. .unitywebgl-container .logo {
    6.    position: absolute;
    7.  
    8.    display: flex;
    9.    align-items: center;
    10.    justify-content: center;
    11.    text-align: center;
    12.  
    13.    color: #fff;
    14.  
    15.    background: #00b7ff;
    16.    border-radius: 50%;
    17.    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.3) inset;
    18. }
    19. .unitywebgl-container .logo.-corner {
    20.    margin: 20px;
    21.    width: 50px;
    22.    height: 50px;
    23.    font-size: 16px;
    24.    background: #ff004c;
    25. }
    26. .unitywebgl-container .logo.-middle {
    27.    width: 150px;
    28.    height: 150px;
    29.    font-size: 22px;
    30. }
    31. .unitywebgl-container .clicktoload {
    32.    cursor: pointer;
    33.  
    34.    position: absolute;
    35.  
    36.    width: 100%;
    37.    height: 100%;
    38.  
    39.    display: flex;
    40.    align-items: center;
    41.    justify-content: center;
    42.  
    43.    box-sizing: border-box;
    44.  
    45.    background: #ffffff;
    46.    border: 10px solid rgba(0,0,0,0.01);
    47.  
    48.    z-index: 999;
    49. }
    50. .unitywebgl-container .canvas {
    51.    width: 100%;
    52. }
     
    Last edited: Nov 7, 2017
    polytropoi and larku like this.