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. Dismiss Notice

HTML - JSLib - Unity communication

Discussion in 'WebGL' started by dchertoff, Jul 22, 2020.

  1. dchertoff

    dchertoff

    Joined:
    May 25, 2020
    Posts:
    7
    It seems to me that there is something missing in the documentation on how to fully handle two-way communication between Unity and content on a webpage.

    Consider the following:

    Use Case 1: Send text from Unity to a text box on a webpage

    In this case, some kind of text string is known by the unity content, and it needs to be sent to the web page. The approach here is to create a jslib that exists within the Unity project for C# code to talk to. The jslib code then communicates with the web page via known, existing function that has been added to the global document.

    However, what if I want to register a callback from the webpage to the jslib, because I am not sure what the webpage developer is going to do? If I want my jslib to just be an API for communicating with the Unity content, is this possible?

    Use Case 2: Send event data from webpage to Unity

    In this use case, the webpage will notify Unity when interaction with a button (or other ui element) occurs. For the example, when the button is pressed, the name of the button is sent to a handler in Unity. We have SendMessage for this, but I it has restrictions on what you can send, it can't return data, and it requires your scene to be configured in a specific way. I would really like to just register a callback from the webpage to the jslib I put in the plugins folder, which in turn triggers a registered callback on the c# side. No restrictions other than what is defined in the API.

    What I have tried:

    jslib
    Code (JavaScript):
    1. var UnityAngularUIBridge =
    2. {
    3.     // Object to hold various callbacks
    4.     $UnityUIBridge:
    5.     {
    6.         dialogTextCallback : null,
    7.         buttonPressedCallback : null
    8.     },
    9.  
    10.     // Called from angular/js side to register a callback for when new dialog text
    11.     // should be displayed
    12.     SetOnDialogTextCallback: function(obj)
    13.     {
    14.         console.log("[UnityAngularUIBridge] SetOnDialogTextCallback");
    15.         console.log(obj);
    16.         UnityUIBridge.dialogTextCallback = obj;
    17.     },
    18.  
    19.     // Called from Unity to indicate that new dialog text should be displayed
    20.     SetDialogText: function (dialogJsonPtr)
    21.     {
    22.         // string paramters from unity get delivered to javascript as pointers.
    23.         // So we get the actual string from the pointer.
    24.         var dialogJson = Pointer_stringify(dialogJsonPtr);
    25.  
    26.         // Now convert the string to a javascript object.
    27.         var dialog = JSON.parse(dialogJson);
    28.  
    29.         // Invoke the provided dialog text callback with the new dialog json
    30.         UnityUIBridge.dialogTextCallback(dialog);
    31.     },
    32.  
    33.     // Called from Unity to set a C# callback for when a button is pressed
    34.     SetOnButtonPressedCallback: function(obj)
    35.     {
    36.         console.log("[UnityAngularUIBridge] SetOnButtonPressedCallback");
    37.         console.log(obj);
    38.         UnityUIBridge.buttonPressedCallback = obj;
    39.     },
    40.  
    41.     // Called from angular/js side when a button is pressed that Unity should
    42.     // know about
    43.     OnButtonPressed: function(buttonName)
    44.     {
    45.         console.log("[UnityAngularUIBridge] OnButtonPressed" + buttonName);
    46.         // Invoke emscripten call with the button callback and required parameter
    47.         Runtime.dynCall('vi', UnityUIBridge.buttonPressedCallback, buttonName);
    48.     },
    49.  
    50. };
    51. autoAddDeps(UnityAngularUIBridge , '$UnityUIBridge');
    52. mergeInto(LibraryManager.library, UnityAngularUIBridge);
    C#
    Code (CSharp):
    1. using System.Runtime.InteropServices;
    2. using AOT;
    3. using UnityEngine;
    4.  
    5. public class UnityAngularUIBridge : MonoBehaviour
    6. {
    7.     /// <summary>
    8.     /// Unity facing event that should handle button presses from the angular UI
    9.     /// </summary>
    10.     public delegate void ButtonCallback(string name);
    11.     public static event ButtonCallback ButtonPressed;
    12.  
    13.     /// <summary>
    14.     /// Callback function definition to be invoked from angular UI
    15.     /// </summary>
    16.     public delegate void JSButtonCallback(System.IntPtr ptr);
    17.  
    18.     [DllImport("__Internal")]
    19.     public static extern void SetOnButtonPressedCallback(JSButtonCallback buttonCallback);
    20.  
    21.     /// <summary>
    22.     /// The function invoked from the javascript bridge
    23.     /// </summary>
    24.     /// <param name="buttonNamePtr">Pointer to data holding the button name</param>
    25.     [MonoPInvokeCallback(typeof(JSButtonCallback))]
    26.     public static void OnButtonClickedCallback(System.IntPtr buttonNamePtr)
    27.     {
    28.         // Convert from byte data into managed string
    29.         string buttonName = Marshal.PtrToStringAuto(buttonNamePtr);
    30.         Debug.Log("Managed string: " + buttonName);
    31.         // Invoke the Unity side event if set
    32.         ButtonPressed?.Invoke(buttonName);
    33.     }
    34.  
    35.     /*
    36.      * For each type of UI control that we want to hook up, the above set of functions
    37.      * will be needed. Add more as new control types are required
    38.      */
    39.  
    40.     [DllImport("__Internal")]
    41.     public static extern void SetDialogText(string jsonData);
    42.  
    43.     [DllImport("__Internal")]
    44.     public static extern void OnButtonPressed(string buttonName);
    45.  
    46.     [DllImport("__Internal")]
    47.     private static extern void SetOnDialogTextCallback(string jsonData);
    48.  
    49.     public void Start()
    50.     {
    51.         // Provide the callback function to the javascript bridge that should be invoked when
    52.         // a button is pressed
    53.         SetOnButtonPressedCallback(OnButtonClickedCallback);
    54.     }
    55. }
    HTML
    Code (CSharp):
    1.       <script>
    2.          // Function which sends the message to Unity
    3.          function OnButtonPressed(buttonName) {
    4.             // Get the input field
    5.             const txtMessage = document.getElementById("txtMessage");
    6.             // Get the message
    7.             const message = txtMessage.value;
    8.             // Clear the input field
    9.             txtMessage.value = "";
    10.  
    11.             // Send message to the Unity scene
    12.             unityInstance.UnityAngularUIBridge.OnButtonPressed(buttonName); // UnityAngularUIBridge is undefined, and whether I do unityInstance._UnityAngularUIBridge or unityInstance.Module._UnityAngularUIBridge or unityInstance.Module.UnityAngularUIBridge, it always stays undefined
    13.          }
    14.       </script>
    Basically, the problem I have is that I am unable to access UnityAngularUIBridge from the webpage side of the equation. I have tried to look through the emscripten documents for help, but I haven't found any example that discusses this in a way that makes sense to me, as those docs are mostly concerned with how to call native code from the jslib in unity, not how to access functions in the jslib from html.

    This thread applies to Unity 2019.4 LTS.
     
  2. lightmapper

    lightmapper

    Joined:
    Jan 14, 2015
    Posts:
    27
    Last edited: Jul 23, 2020
  3. De-Panther

    De-Panther

    Joined:
    Dec 27, 2009
    Posts:
    552
  4. ickydime

    ickydime

    Joined:
    Nov 20, 2012
    Posts:
    110
    @De-Panther Would be curious to see these examples if they are still available. Currently getting a 404
     
  5. De-Panther

    De-Panther

    Joined:
    Dec 27, 2009
    Posts:
    552
    tonialatalo likes this.