Calling JS code defined or loaded from HTML for WebGL game

I have a WebGL game that I want to call a method on the html launching the game…

Given this html which is based on the Unity default WebGL html wrapper:

<!DOCTYPE html>
<html lang="en-us">
<head>
    <meta charset="utf-8">
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <title>%UNITY_WEB_NAME%</title>
    <link href="TemplateData/favicon.ico" rel="shortcut icon">
    <link href="TemplateData/style.css" rel="stylesheet">
    <script src="TemplateData/UnityProgress.js">
    </script>
    <script src="%UNITY_WEBGL_LOADER_URL%">
    </script>
    <script>
          var gameInstance = UnityLoader.instantiate("gameContainer", "%UNITY_WEBGL_BUILD_URL%", {
              onProgress: UnityProgress
          });
    </script>
</head>
<body>
    <button id="playButton" type="button">Do It</button>
    <script src="https://somedomain.com/uber-script.js" type='text/javascript'>
    </script>
    <script type="application/javascript">
          function myCallback(status) {
              console.log('Status:', status);
          }

          var options = {
              x: 1,
              y: 1,
              z: 3
          };
          playBtn = document.getElementById("playButton");
          playBtn.onclick = function() {
              invokeMyMethod(options); // is defined in https://somedomain.com/uber-script.js
          }
    </script>
    <div class="webgl-content">
        <div id="gameContainer" style="width: %UNITY_WIDTH%px; height: %UNITY_HEIGHT%px"></div>     
    </div>
</body>
</html>

I’m wanting to invoke the method “invokeMyMethod” which is defined and loaded by the html from somedomain.com

How would I call this method?

I’ve got a jslib like so:

Assets/Plugins/WebGL/applixir.jslib
mergeInto(LibraryManager.library, {

  MyFunction: function () {
    var options = {
        x: 1,
        y: 1,
        z: 3,
    };
 
    invokeMyMethod(options); // hoping magic would make this find the correct method to call.
  },
});

And then I include that the standard way:

public class TestButton : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern void PlayVideo();

    public void onClick()
    {
        PlayVideo();
    }
}

But obviously this is not compiling since there are undefined references in the jslib…

What am I doing wrong?

Note, I have this running perfectly well using the old and deprecated Application.ExternalCall(…) which is great, but not a long term solution…

Any guidance would be great.

Bump.

Surely someone at Unity knows how to do this?

I’ve gotten this working without issue. Do you get any error output on the Javascript console?

Hey TheRoccoB,

I think I’ve actually got a little further today. What I have:

JSLIB:

var MyPlugin = {
    $impl: {},
    statusCallback: function (status) {
 
            console.log('status:', status);
     
            var iresult = 0;
     
            Runtime.dynCall('vi', window.unityMethodCallback, [iresult]);
     
            console.log('status done:', status);
     
    },
    ShowVideo__deps: [
       '$impl',
        'statusCallback'
    ],
    ShowVideo: function (devId, callback) { 
         
       var local_options = {        
              devId: devId,
              adStatusCb: statusCallback /* 3rd party will invoke this callback */
            };
     
            console.log(local_options);
     
            // Save the Unity method callback reference as a global to use in statusCallback when invked by 3rd party
            window.unityMethodCallback = callback;
     
            //
            // I have tried simply invoking this here to test
            //
            //Runtime.dynCall('vi', window.unityMethodCallback, [88]);
                 
            //
            // Invoke the third party, shows an iframe over ours and then calls back to callback passed in options.
            //
            invokeThirdPartyScriptThatWillCallMeBackLater(local_options);
    }
};
autoAddDeps(MyPlugin, '$impl');
mergeInto(LibraryManager.library, MyPlugin);

I expect I don’t need the manually added __deps since I’m auto adding underneath, but it’s where I’m at with trying things.

This builds and my calls make it through to ShowVideo in jslib, but trying to reference statusCallback from ShowVideo always gives me an undefined reference error (eg: ReferenceError: statusCallback is not defined at _ShowVideo)

Any ideas?

Edit: I just noticed that ShowVideo becomes _ShowVideo. I’m now building trying the same but referencing _statusCallback - building now … … …

Ha, that was it…

The method I was referencing was getting name mangled (well and underscore prepended)…

Working!

@larku I know this is about 8 months old, but I was wondering if you could clarify a bit what you actually did to get things working. I am having the exact same problem you describe, and I’m at the point where I get the “ReferenceError: method is not defined” error message. Where exactly did you place an underscore, and how did you find ShowVideo becoming _ShowVideo?

There are a few other places I’ve found online, namely this post, which also hint at needing to prefix your calls to methods defined elsewhere in the jslib with an underscore. But, to use your above code as an example, if I change line 22 to be:
adStatusCb: _statusCallback then I still get “_statusCallback is not defined”.

Were you able to remove the explicit __deps declaration with autoAddDeps at the bottom?