Home > Enterprise >  How can i connect Buttons from my Index.html to my Unity Code
How can i connect Buttons from my Index.html to my Unity Code

Time:11-18

`I have a Unity 3D Project where i can drive around with a forklift and i want to add features like picking stuff up, putting it down and colorize materials. But I have a problem with connecting the buttons (which I made in the index.html, which is generated when i run my project with webgl) with my unity code. The webgl page looks like this: my project

I already tried it with UnityLoader.instantiate but it does not work for me i get the following error: UnityLoader - error

Here is the script from my Index.html `

    <script>
      var container = document.querySelector("#unity-container");
      var canvas = document.querySelector("#unity-canvas");
      var loadingBar = document.querySelector("#unity-loading-bar");
      var progressBarFull = document.querySelector("#unity-progress-bar-full");
      var fullscreenButton = document.querySelector("#unity-fullscreen-button");
      var warningBanner = document.querySelector("#unity-warning");

      function unityShowBanner(msg, type) {
        function updateBannerVisibility() {
          warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';
        }
        var div = document.createElement('div');
        div.innerHTML = msg;
        warningBanner.appendChild(div);
        if (type == 'error') div.style = 'background: red; padding: 10px;';
        else {
          if (type == 'warning') div.style = 'background: yellow; padding: 10px;';
          setTimeout(function() {
            warningBanner.removeChild(div);``
            updateBannerVisibility();
          }, 5000);
        }
        updateBannerVisibility();
      }

      var buildUrl = "Build";
      var loaderUrl = buildUrl   "/build.loader.js";
      var config = {
        dataUrl: buildUrl   "/build.data",
        frameworkUrl: buildUrl   "/build.framework.js",
        codeUrl: buildUrl   "/build.wasm",
        streamingAssetsUrl: "StreamingAssets",
        companyName: "DefaultCompany",
        productName: "warehouseOnline3D",
        productVersion: "0.1",
        showBanner: unityShowBanner,
      };

  
      if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
        // Mobile device style: fill the whole browser client area with the game canvas:

        var meta = document.createElement('meta');
        meta.name = 'viewport';
        meta.content = 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes';
        document.getElementsByTagName('head')[0].appendChild(meta);
        container.className = "unity-mobile";

        // To lower canvas resolution on mobile devices to gain some
        // performance, uncomment the following line:
        // config.devicePixelRatio = 1;

        canvas.style.width = window.innerWidth   'px';
        canvas.style.height = window.innerHeight   'px';

        unityShowBanner('WebGL builds are not supported on mobile devices.');
      } else {
        // Desktop style: Render the game canvas in a window that can be maximized to fullscreen:

        canvas.style.width = "960px";
        canvas.style.height = "600px";
      }

      loadingBar.style.display = "block";

      var script = document.createElement("script");
      script.src = loaderUrl;
      script.onload = () => {
        createUnityInstance(canvas, config, (progress) => {
          progressBarFull.style.width = 100 * progress   "%";
        }).then((unityInstance) => {
          loadingBar.style.display = "none";

          fullscreenButton.onclick = () => {
            unityInstance.SetFullscreen(1);
          };
        }).catch((message) => {
          alert(message);
        });
      };
      document.body.appendChild(script);
      
      var gameInstance = UnityLoader.instantiate("gameContainer", "Build/webgl.json");
      
      gameInstance.SendMessage("Sideloader", "test", "printed from webgl");  
    </script>

the function that should be called from the UnityLoader

CodePudding user response:

The way via the UnityLoader afaik is from very early Unity WebGL versions.


You want to store the result of the createUnityInstance within the then block and then use it later like

<script>
    let instance = null;
    
    ....
    
    createUnityInstance(canvas, config, (progress) => {
          progressBarFull.style.width = 100 * progress   "%";
        }).then((unityInstance) => {
          instance = unityInstance;
    ...

then you can later on use it and do

instance.SendMessage("Sideloader", "test", "printed from webgl"); 

However you can not do this in the current spot in the script initilazation level. You will have to wait until that then block was actually called and then do it for your button e.g.

<button onclick='ButtonClick()'>test</button>

...

function ButtonClick()
{
    if(instance) instance.SendMessage("Sideloader", "test", "printed from webgl"); 
}

As a more complex alternative though you can implement a plugin and let the c# part inject a callback into it you can later call and once your project gets more complex you might want to go with that rather.

E.g. have a MyFancyPlugin.jslib

var myFancyPlugin = {
{    
    $CallbackPtr : {},

    InitializeJavaScript : function(callbackPtr)
    {
        CallbackPtr = callbackPtr;
    }

    FancyCall : function(value)
    {
        const valueSize = lengthBytesUTF8(value) 1;
        const valueBuffer = _malloc(dataUrlSize);
        stringToUTF8(value, valueBuffer, valueSize);
        Runtime.dynCall("vi", $CallbackPtr, [valueBuffer]);
        free(valueBuffer);
    }
};
autoAddDeps(myFancyPlugin, '$CallbackPtr');
mergInto(LibraryManager.library, myFancyPlugin);

and on your button do e.g.

<button onclick='FancyCall("TEST!")'>test</button>

and then in c# have something like e.g.

public static class MyFancyPlugin
{
    private delegate void Callback(string value);

    [DllImport("__Internal")]
    private static void InitializeJavaScript(Callback callback);

    public static void Initialize()
    {
        InitializeJavaScript(OnCallbackReceived);
    }

    [MonoPInvokeCallback(typeof(Callback))]
    private static void OnCallbackReceived(string value)
    {
        Debug.Log("Received from JavaScript: {value}");
    }
}

where something has to call

MyFancyPlugin.Initialize();

of course

  • Related