Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Start Unity Player on Button click

Discussion in 'WebGL' started by pera2, Aug 10, 2016.

  1. pera2

    pera2

    Joined:
    Aug 10, 2016
    Posts:
    14
    At the moment, Player starts as soon as test page is loaded. I want user to click on the button on webpage to start loading unity content. I tried editing UnityLoader.js but only managed to break it.
     
  2. alexsuvorov

    alexsuvorov

    Unity Technologies

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

    The appropriate solution would depend on the specific use case:

    a) The user is expected to click the play button at some point, in which case WebGL content should be loaded in background and get ready for immediate start when user clicks the button.

    b) The user might skip playing the game, in which case you may consider loading all the content after he clicks the button (the same strategy applies to a situation when there are several games on the screen, while user might play only one of them). In this case the startup of the game will take longer, but there will be no unnecessary loading if the user does not play it.

    Which situation fits you better?
     
  3. pera2

    pera2

    Joined:
    Aug 10, 2016
    Posts:
    14
  4. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    The thing is that by the time the UnityLoader.js is run it is already a bit too late to pause the loading process. It would be therefore more appropriate to just delay the loader execution. You can do this by overriding the Default html template (see additional info here https://docs.unity3d.com/Manual/webgl-templates.html).

    All you need to do is to add a Play button to the page and manually expand the %UNITY_WEBGL_LOADER_GLUE% variable with the following content:
    Code (html):
    1. <!doctype html>
    2. <html lang="en-us">
    3.   <head>
    4.     <meta charset="utf-8">
    5.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    6.     <title>Unity WebGL Player | %UNITY_WEB_NAME%</title>
    7.     <link rel="stylesheet" href="TemplateData/style.css">
    8.     <link rel="shortcut icon" href="TemplateData/favicon.ico" />
    9.     <script src="TemplateData/UnityProgress.js"></script>
    10.   </head>
    11.   <body class="template">
    12.     <div class="template-wrap clear">
    13.       <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" height="%UNITY_HEIGHT%px" width="%UNITY_WIDTH%px"></canvas>
    14.       <br>
    15.       <button type="button" class="template-wrap" style="z-index:10" onclick="runUnityLoader(); style.display='none';">Play</button>
    16.       <div class="logo"></div>
    17.       <div class="fullscreen"><img src="TemplateData/fullscreen.png" width="38" height="38" alt="Fullscreen" title="Fullscreen" onclick="SetFullscreen(1);" /></div>
    18.       <div class="title">%UNITY_WEB_NAME%</div>
    19.     </div>
    20.     <script type='text/javascript'>
    21.       var Module = {
    22.         TOTAL_MEMORY: %UNITY_WEBGL_TOTAL_MEMORY%,
    23.         errorhandler: null,            // arguments: err, url, line. This function must return 'true' if the error is handled, otherwise 'false'
    24.         compatibilitycheck: null,
    25.         dataUrl: "%UNITY_WEBGL_DATA_FOLDER%/%UNITY_WEBGL_FILE_NAME%.data",
    26.         codeUrl: "%UNITY_WEBGL_DATA_FOLDER%/%UNITY_WEBGL_MAIN_MODULE_FILE_NAME%.js",
    27.         memUrl: "%UNITY_WEBGL_DATA_FOLDER%/%UNITY_WEBGL_MAIN_MODULE_FILE_NAME%.mem",
    28.       };
    29.       function runUnityLoader() {
    30.         var script = document.createElement("script");
    31.         script.src = "%UNITY_WEBGL_DATA_FOLDER%/UnityLoader.js";
    32.         document.body.appendChild(script);
    33.       }
    34.     </script>
    35.   </body>
    36. </html>
    If for some reason it does not work as expected for you, let me know your exact Unity version.
     
  5. pera2

    pera2

    Joined:
    Aug 10, 2016
    Posts:
    14
    Thanks for reply, it works good.

    Do you think in the future UnityLoader.js could have some starting function that can be commented out and called at later stage? Is there some issues with this approach that Im not seeing?
     
    Last edited: Aug 12, 2016
  6. notsure1337

    notsure1337

    Joined:
    Dec 4, 2016
    Posts:
    4
    I just can't find the %UNITY_WEBGL_LOADER_GLUE% , did you mean %UNITY_WEBGL_LOADER_URL% ? I just replaced the html template with provided content, but it did not work. Im not a Java/HTML Expert, may you can give some more detailed instructions where to replace it.



    Unity Version: 2017.3.0p1
     
  7. notsure1337

    notsure1337

    Joined:
    Dec 4, 2016
    Posts:
    4
    Would alex solution prevent asm.js to be compiled before the button is pressed? Can please anyone explain what purpose the module has and why there is a canvas used?


    Here is my working example, that I understand. Sorry im a designer..do laugh.. ^^

    the gameInstance var will be declared outside to make it global.

    if you compile it with the default template this is how to :

    Code (csharp):
    1. <!-- insert this to your websites body by replacing it with the existing webgl-content div -->
    2.  
    3. <div class="webgl-content">
    4.       <div id="gameContainer" style="width: 960px; height: 600px"></div>
    5.       <button type="button" style="z-index:10000" onclick="runUnityLoader(); style.display='none';">Play</button>
    6.       <div class="footer">
    7.         <div class="webgl-logo"></div>
    8.         <div class="fullscreen" onclick="window.gameInstance.SetFullscreen(1)"></div>
    9.         <div class="title">Name of the game</div>
    10.       </div>
    11.     </div>
    12.  
    13.  
    14.  
    15.  
    16. <!-- paste this after the body -->
    17.  
    18. <script>
    19. var gameInstance;
    20.  
    21. function runUnityLoader() {
    22.   gameInstance = UnityLoader.instantiate("gameContainer", "Build/portalsweb.json", {onProgress: UnityProgress});
    23. }
    24. </script>
    25.  
     
  8. LikhitaBiyyala

    LikhitaBiyyala

    Joined:
    Aug 21, 2020
    Posts:
    1
    Hello,
    I am looking some what similiar way,once the progress bar is completely loaded,a play button will appear and when the user click on the play button on webpage, it should start loading unity content. Is this possible???
     
    Last edited: Sep 21, 2020
  9. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    944
    If you look at the current index.html template, it reads

    Code (CSharp):
    1. <!DOCTYPE html>
    2. <html lang="en-us">
    3.   <head>
    4.     <meta charset="utf-8">
    5.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    6.     <title>Unity WebGL Player | {{{ PRODUCT_NAME }}}</title>
    7.   </head>
    8.   <body style="text-align: center">
    9.     <canvas id="unity-canvas" style="width: {{{ WIDTH }}}px; height: {{{ HEIGHT }}}px; background: {{{ BACKGROUND_FILENAME ? 'url(\'Build/' + BACKGROUND_FILENAME.replace(/'/g, '%27') + '\') center / cover' : BACKGROUND_COLOR }}}"></canvas>
    10.     <script src="Build/{{{ LOADER_FILENAME }}}"></script>
    11.     <script>
    12.       createUnityInstance(document.querySelector("#unity-canvas"), {
    13.         dataUrl: "Build/{{{ DATA_FILENAME }}}",
    14.         frameworkUrl: "Build/{{{ FRAMEWORK_FILENAME }}}",
    15.         codeUrl: "Build/{{{ CODE_FILENAME }}}",
    16. #if MEMORY_FILENAME
    17.         memoryUrl: "Build/{{{ MEMORY_FILENAME }}}",
    18. #endif
    19. #if SYMBOLS_FILENAME
    20.         symbolsUrl: "Build/{{{ SYMBOLS_FILENAME }}}",
    21. #endif
    22.         streamingAssetsUrl: "StreamingAssets",
    23.         companyName: "{{{ COMPANY_NAME }}}",
    24.         productName: "{{{ PRODUCT_NAME }}}",
    25.         productVersion: "{{{ PRODUCT_VERSION }}}",
    26.       });
    27.     </script>
    28.   </body>
    29. </html>
    30.  
    If you would instead like to instantiate the game on a button click, you would defer the call to `createUnityInstance()` behind a button click event, something like

    Code (CSharp):
    1. <!DOCTYPE html>
    2. <html lang="en-us">
    3.   <head>
    4.     <meta charset="utf-8">
    5.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    6.     <title>Unity WebGL Player | {{{ PRODUCT_NAME }}}</title>
    7.   </head>
    8.   <body style="text-align: center">
    9.     <button id='loadbutton' value='load'>Load</button>
    10.     <canvas id="unity-canvas" style="width: {{{ WIDTH }}}px; height: {{{ HEIGHT }}}px; background: {{{ BACKGROUND_FILENAME ? 'url(\'Build/' + BACKGROUND_FILENAME.replace(/'/g, '%27') + '\') center / cover' : BACKGROUND_COLOR }}}"></canvas>
    11.     <script src="Build/{{{ LOADER_FILENAME }}}"></script>
    12.     <script>
    13.       document.queryElementById('load').addEventListener('click', function() {
    14.       createUnityInstance(document.querySelector("#unity-canvas"), {
    15.         dataUrl: "Build/{{{ DATA_FILENAME }}}",
    16.         frameworkUrl: "Build/{{{ FRAMEWORK_FILENAME }}}",
    17.         codeUrl: "Build/{{{ CODE_FILENAME }}}",
    18. #if MEMORY_FILENAME
    19.         memoryUrl: "Build/{{{ MEMORY_FILENAME }}}",
    20. #endif
    21. #if SYMBOLS_FILENAME
    22.         symbolsUrl: "Build/{{{ SYMBOLS_FILENAME }}}",
    23. #endif
    24.         streamingAssetsUrl: "StreamingAssets",
    25.         companyName: "{{{ COMPANY_NAME }}}",
    26.         productName: "{{{ PRODUCT_NAME }}}",
    27.         productVersion: "{{{ PRODUCT_VERSION }}}",
    28.       });
    29. });
    30.     </script>
    31.   </body>
    32. </html>
    33.  
    Notice how the instantiation will not start immediately, but only when the click handler is run.
     
  10. mrcoffeedrinkingman

    mrcoffeedrinkingman

    Joined:
    Dec 5, 2020
    Posts:
    1
    This template sadly doesn't work in 2019.4.
     
  11. Inter42

    Inter42

    Joined:
    May 17, 2021
    Posts:
    13
    I came across this from a search result. If anyone else is trying to achieve this in 2021, here's how I went about it:

    Add
    <button id="unity-load-button">start loading</button>
    somewhere on your page (I put it just after the #unity-canvas). Use CSS to place it somewhere nice like right above the default loading bar. Example CSS:
    Code (CSharp):
    1. #unity-load-button {
    2.     display: inline-block;
    3.     position: absolute;
    4.     top: 40%;
    5.     left: 50%;
    6.     transform: translate(-50%,-50%);
    7.     z-index: 10;
    8. }
    Then modify the default javascript which calls createUnityInstance() so it only calls *after* you press the button, and then disable & hide the button once loading starts.

    To do this, I just changed this:
    Code (CSharp):
    1. script.onload = () => {
    2.         createUnityInstance(canvas, config, (progress) => {
    3.           progressBarFull.style.width = 100 * progress + "%";
    4.         }).then((unityInstance) => {
    5.           loadingBar.style.display = "none";
    6.           fullscreenButton.onclick = () => {
    7.             unityInstance.SetFullscreen(1);
    8.           };
    9.         }).catch((message) => {
    10.           alert(message);
    11.         });
    12.       };
    into this:
    Code (CSharp):
    1. loadButton.addEventListener("click", function() {
    2.                   createUnityInstance(canvas, config, (progress) => {
    3.                     progressBarFull.style.width = 100 * progress + "%";
    4.                   }).then((unityInstance) => {
    5.                     loadingBar.style.display = "none";
    6.                     loadButton.style.display = "none";
    7.                     loadButton.disabled = true;
    8.                     fullscreenButton.onclick = () => {
    9.                       unityInstance.SetFullscreen(1);
    10.                     };
    11.                   }).catch((message) => {
    12.                     alert(message);
    13.                   });
    14.                 });
    (where loadButton was previously defined as
    var loadButton = document.querySelector("#unity-load-button");
    )


    Working example: https://michaelcassidy.net/post/testing-custom-hugo-page-template-for-unity-webgl-builds/

    Hope this helps someone.


    EDIT: actually you probably want to disable the load button as soon as it's clicked, in case someone spam clicks it.

    So put this somewhere in the script too:
    Code (CSharp):
    1. loadButton.addEventListener("click", function() {
    2.     loadButton.disabled = true;
    3. });
     
    Last edited: Jun 24, 2021
    AliceWasNeverHere likes this.
  12. Inter42

    Inter42

    Joined:
    May 17, 2021
    Posts:
    13
  13. santi2493

    santi2493

    Joined:
    Jan 22, 2014
    Posts:
    8
    Here is a fix for @jukka_j solution. I think was a refence problem to the button. Thanks everyone for the help

    Code (JavaScript):
    1. <!DOCTYPE html>
    2. <html lang="en-us">
    3. <head>
    4.     <meta charset="utf-8">
    5.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    6.     <title>Unity WebGL Player | {{{ PRODUCT_NAME }}}</title>
    7. </head>
    8. <body style="text-align: center">
    9.     <button id='loadbutton' value='load'>Load</button>
    10.     <canvas id="unity-canvas" width={{{ WIDTH }}} height={{{ HEIGHT }}} style="width: {{{ WIDTH }}}px; height: {{{ HEIGHT }}}px; background: {{{ BACKGROUND_FILENAME ? 'url(\'Build/' + BACKGROUND_FILENAME.replace(/'/g, '%27') + '\') center / cover' : BACKGROUND_COLOR }}}"></canvas>
    11.     <script src="Build/{{{ LOADER_FILENAME }}}"></script>
    12.     <script>
    13.         document.getElementById('loadbutton').addEventListener('click', function () {
    14.             document.getElementById("loadbutton").disabled = true;
    15.      
    16.       createUnityInstance(document.querySelector("#unity-canvas"), {
    17.         dataUrl: "Build/{{{ DATA_FILENAME }}}",
    18.         frameworkUrl: "Build/{{{ FRAMEWORK_FILENAME }}}",
    19.         codeUrl: "Build/{{{ CODE_FILENAME }}}",
    20. #if MEMORY_FILENAME;
    21.         memoryUrl: "Build/{{{ MEMORY_FILENAME }}}",
    22. #endif
    23. #if SYMBOLS_FILENAME
    24.         symbolsUrl: "Build/{{{ SYMBOLS_FILENAME }}}",
    25. #endif
    26.         streamingAssetsUrl: "StreamingAssets",
    27.         companyName: "{{{ COMPANY_NAME }}}",
    28.         productName: "{{{ PRODUCT_NAME }}}",
    29.         productVersion: "{{{ PRODUCT_VERSION }}}",
    30.         // matchWebGLToCanvasSize: false, // Uncomment this to separately control WebGL canvas render size and DOM element size.
    31.         // devicePixelRatio: 1, // Uncomment this to override low DPI rendering on high DPI displays.
    32.         });
    33.       });
    34.     </script>
    35. </body>
    36. </html>
     
    Last edited: Jun 16, 2022