Browser scripting and function calling

I am trying to create a WebGL plugin that uses an external javascrip library to call functions on the web browser.
I have followed the instructions here (Unity - Manual: WebGL: Interacting with browser scripting) on calling external javascript functions and can successfully call functions held in .jslib files. My problem is that I can not get javascript functions held in .jslib files to call other javascript funcitons correctly.

for example the following java script file throws an undefined error when Testfunction1 is called via c#

var TestFunctions =
{   
    InternalFunctionCall: function ()
    {
        window.alert(" Function Called");

    },
   
    TestFunction1: function ()
    {
        InternalFunctionCall();
    },
}
mergeInto(LibraryManager.library, TestFunctions);

I have tried defining the functions using ExternalEval (Unity - Scripting API: Application.ExternalEval) or storing the functions in other .jslib files but nothing works they always throw an Undefined error when called.

How do i call external java script functions? How do I integrate an external .jslib Library into a WebGL project?

source:New Unity WebGL Embedding API White Paper - Unity Engine - Unity Discussions

myGame.SendMessage("myObject", "myFunction", "foobar");

here is a example for image download: User image download from in webgl app

1 Like

Thanks for replying but I don’t think this addresses my issue.
Just to clarify my issue is NOT calling unity c# functions from browser scripting its calling one custom java script function from another.

my issue is I have created a custom javascript .jslib library that I am using to do browser peer to peer communication as well as other things but I am having trouble calling the functions in the library via a unity wrapper. every time I call a function from within another javascript function Unity throws a not defined exception.

what about this method ?

var TestFunctions =
{
    $impl: {
        internalFunctionCall: function()
        {
            window.alert(" Function Called");
        },
    },

    InternalFunctionCall: function ()
    {
        impl.internalFunctionCall();
    },
};

autoAddDeps(TestFunctions, '$impl');
mergeInto(LibraryManager.library, TestFunctions);

This way you could call the actual implementation from any function of the library.

We use the same technique in FileSystem.js (\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\lib).

3 Likes

This works great thanks but it opens up another issue. Is there any way to call/link functions held in external files? I have a custom library held in a .jslib file that I want to call functions on but I don’t know how to link it into the project.

I was looking at other examples and they were loading in library’s as text files then using https://docs.unity3d.com/ScriptReference/Application.ExternalEval.html to run the script and setup the java classes which seems to work (it runs the code at least ) but when I try to access the classes it sets up I get an undefined error.

Is there a clear and idiot friendly explanation of how the external code is being called? I have a lot of experience with c++ and C# but just started with java script and things that work on a non unity web page throw errors when implemented with unity.

Do you just want to call jslib functions from C#? If so, then this page should all the info. You could also look at one of the asset store packages, for example this one.

sry, i was reading the first post again.

You want call a javascript function located in a HTML file from a jslib?
or just a function from a different function?

var MyJslibPlugin = {
  MyJslibName: function() {
      function subfunction()
      {
        return something;
      }
      var result = subfunction();
    }
}

Well, i think i did understand the problem.
You try to write all functions in one single jslib file. I never did this. But pearhaps you can just delete the last comma after the last function.

EDIT:
and add a ; after the last }

To clarify my problem here are a few more details.

My current goal is to connect a bunch of non unity web pages to a single instance of Unity via webRTC peer to peer connections.

rough diagram of my program structure.


I have written a class object in java script to handle a single network instance this is a simplified version of it

function WebRTCPrototype()
{
    this.WebRTCConnection = null;

    this.Connect = function(target, callback)
    {
        //create new connection
        this.WebRTCConnection = new WebRTCConnection ();

        //connect to target
        this.WebRTCConnection.ConnectTo(target);

        //set callback when message is received
        this.WebRTCConnection.OnMessageCallback = callback;
    }

    this.SendMessage = function(message)
    {
        this.WebRTCConnection.SendMessage(message);
    }

}

the networking instance class handles the connection for both the unity connection and the browser controller connection.

because I need a unique instance of the network instance class for each connection a wrapper class is needed to give unity a single point of entry into the networking library.

this is a simplified version of the unity wrapper

var UnityWrapper =
{
    var Connections ;

    var Message ;

   //create new network instance
    CreateConnection: function(Target,ID)
   {
        //create new networking instance
         var Connection = new WebRTCPrototype();

        //connect to target and set callback
        Connection.connect(target,OnMessage)
    
       //store connection in dictionary array
        Connections[id] = Connection

   }

    //callback called when message received
    OnMessage: function(message)
    {
        Message = message;
    }

    //c# access point to get message
    GetMessage: function()
   {
        return Message;
   }

    //send a message to a specific target
    SendMessage: function(ID,message)
    {
        Connections[id].SendMessage(message);
    }

}

I can call functions from C# no problem its calling a java script function in one file from another that’s causing the problem.

@jack-riddell , I realize this is over a year old but were you able to find a solution?

I have the same problem you describe in your original post, albeit my scenario is much simpler.

Following the documentation example, I have a .jslib file containing the methods which Unity calls. Abbreviated:

mergeInto(LibraryManager.library, {

    SCOInitialize: function() {
        return doInitialize();
    },

    doInitialize: function() {
       window.alert("LMS Communication successful!");
       return true;
    },

});

(I realize the above snippet looks redundant, but it’s a simplified version of my use case.)

I also have the corresponding Unity C# script. Snipped:

[DllImport("__Internal")]
private static extern bool SCOInitialize();

void Start()
{
    SCOInitialize();
}

Unity successfully calls the external SCOInitialize function, but when SCOInitialize then tries to call doInitialize() - which is right freaking there! - I get the popup error on the page:

This doesn’t make sense to me as doInitialize is VERY CLEARLY DEFINED! So, what gives?

I had a quick look through the jslib files in the PlaybackEngines\WebGLSupport\BuildTools\lib to see if any existing jslib files call methods in the same file.

It looks like you might have to prefix your method call with an underscore.
This is what audio.js does:

{
// stop sound which is playing in the channel currently.
_JS_Sound_Stop (channelInstance, 0);
...
}

JS_Sound_Stop: function (channelInstance, delay)
{
...
}```

I think you need the underscore prefix and you need to add doInitialize() as a dependency of SCOInitialize() otherwise it will be stripped since it’s not referenced by the C# script:

mergeInto(LibraryManager.library, {
   SCOInitialize__deps: ['doInitialize'],
   SCOInitialize: function() {
      return _doInitialize();
   },
   doInitialize: function() {
      window.alert("LMS Communication successful!");
      return true;
   },
});
2 Likes

Thanks, that appears to have done the trick.

I started learning about the dependency stuff late in the evening after my above reply and still spent a while trying to get the syntax right. Having to define the __deps line before every method that wants to use another method in the library seems obtuse and kind of messy. I’ve seen a few examples of “autoAddDeps” that purport to be a simpler, cleaner alternative but I could never quite get that syntax to work either.

I feel like what I’m trying to do (call one jslib function from another) is pretty basic - the WebGL: Interacting with browser scripting page should really cover how to solve this problem since jslib’s format is so different from regular JavaScript.

Anyway I’ve finally got things working!

Our documentation also says “For more information on how to interact with JavaScript, refer to the emscripten documentation.” :slight_smile:

And the emscripten documentation is a confusing mess as a Unity developer. I am not a JavaScript programmer or a C/C++ programmer (the intended audience of the documentation). Can you point out where in the documentation it gives the solution? Because I definitely looked! I personally don’t have enough familiarity or understanding of emscripten to grok the solution I’m looking for because I don’t know where to look, and I would wager many Unity game developers are in the same boat. Like I said, the problem I was trying to solve seems (to me) like something that lots of people reading the Unity documentation will probably run into, so why not add an extra blurb explaining the solution?

2 Likes

I have to admit I had to look at examples to figure out how this works. The main reason why we don’t have much in our docs regarding js libs is that it really depends on emscripten and we would need to keep our documentation updated.

Having said that, you are probably right. We should add a short explanation about this…

bsawyer I suspect we’re working on the same type of project based on the function names in your code snippits. Maybe even in same building. Did you ever figure out things on your end? I’m on a project that used to be WebPlayer but is being converted to WebGL (5.6.2.x). I too came across the same unity documentation you did and started moving the .js files that used to be external to the Plugins folder as .jslibs. The first file seemed fine, but it was only a single function. The next file has a bunch of functions but also vars that aren’t part of functions. The unity documentation shows the syntax for functions, what’s the syntax for vars?

I’m also stuck on this issue: How to call external .js function from unity .jslib plugin?
I’ve read every article, tried it all - been at it for the past week with no solution.

Unity - we understand your scope of responsibility stops right about here, at the jsplugin, but we need support to interface with the outside world.

We are trying to expand the horizons of unity and its use cases but need your guidance.

1 Like

@anon_35490856 please, we are already having an active communication thread at Call JavaScript function in index.html from WebGL , posting on other threads will not help the matter and just introduces unwanted noise to litter other people’s problem threads. Let’s focus on good forum etiquette and the thread where we are actively looking at the problem at hand.

1 Like