Search Unity

  1. Engage, network and learn at Unite Austin 2017, Oct 3 - 5. Get your ticket today!
    Dismiss Notice
  2. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  3. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  4. Unity 2017.1 is now released.
    Dismiss Notice
  5. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice
  6. Unity 2017.2 beta is now available for download.
    Dismiss Notice

Super fast Javascript interaction on WebGL

Discussion in 'WebGL' started by atti, Jan 29, 2016.

  1. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    Hi folks,

    I figured something out worth sharing maybe:

    Source:
    https://github.com/atteneder/UnityJavascriptInteraction

    I'm on a project where we do heavy Javascript interaction with Unity and we're not happy with the SendMessage interface Unity provides.
    • It's slow (on my machine around 0.1 ms overhead per call, which is problematic to me).
    • It's limited to three parameter variants in JS: void, Number, String
    • You need extra glue code and calls to come up for the lack of return values.
    So I tried this:
    • Native C function that sets a callback to a static C# method. This is called on Awake somewhere.
    • Native C function that calls the callback.
    • Setting the emscriptenArgs to also export my caller C function.
    • Export, fire up a browser.
    • Call via emscripten's ccall.
    • Call the function with both methods 10000 times and measure the results.
    Here you go, in Chrome:
    Bildschirmfoto 2016-01-29 um 15.19.54.png

    Firefox is even faster:
    Bildschirmfoto 2016-01-29 um 15.54.14.png

    I attached the complete Unity project so you can fiddle with it.

    Notes:
    • I haven't covered passing parameters back and forth yet, which is not straight forward since you need some conversions / memory operations.
    • @Unity: It would be nice to have a (hidden) setting like "emscriptenArgs" that allows to give additional function names to emscripten's "-s EXPORTED_FUNCTIONS" parameter. I basically had to override it.
    Hope you find this helpful,
    atti

    EDIT:
    I'll update this post if I have new info to share:
    - Removed original source, added super-social GitHub link instead.
    - cwrap makes things even speedier! (thanks alexsuvorov)
     
    Last edited: Jan 29, 2016
  2. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Hello atti.

    This is a very interesting observation. I have just tested your code and it does show significant overhead for SendMessage calls. Moreover, it appears that it is not the SendMessage itself that causes the overhead, but the accompanying Module.cwrap(), which creates a JavaScript function within each SendMessage call.

    Let's examine the original code:
    Code (JavaScript):
    1. function SendMessage(gameObject, func, param)
    2. {
    3.     if (param === undefined)
    4.         Module.cwrap('SendMessage', 'void', ['string', 'string'])(gameObject, func);
    5.     else if (typeof param === "string")
    6.         Module.cwrap('SendMessageString', 'void', ['string', 'string', 'string'])(gameObject, func, param);
    7.     else if (typeof param === "number")
    8.         Module.cwrap('SendMessageFloat', 'void', ['string', 'string', 'number'])(gameObject, func, param);
    9.     else
    10.         throw "" + param + " is does not have a type which is supported by SendMessage.";
    11. }
    which gives us
    Screen Shot 2016-01-29 at 21.43.03.png

    Now if we modify the code a bit so that the wrappers are generated only once, for example:
    Code (JavaScript):
    1. function SendMessage(gameObject, func, param)
    2. {
    3.     if (param === undefined) {
    4.       if (typeof this.SendMessage_vss != 'function')
    5.         this.SendMessage_vss = Module.cwrap('SendMessage', 'void', ['string', 'string']);
    6.       this.SendMessage_vss(gameObject, func);
    7.     } else if (typeof param === "string") {
    8.       if (typeof this.SendMessage_vsss != 'function')
    9.         this.SendMessage_vsss = Module.cwrap('SendMessageString', 'void', ['string', 'string', 'string']);
    10.       this.SendMessage_vsss(gameObject, func, param);
    11.     } else if (typeof param === "number") {
    12.       if (typeof this.SendMessage_vssn != 'function')
    13.         this.SendMessage_vssn = Module.cwrap('SendMessageFloat', 'void', ['string', 'string', 'number']);
    14.       this.SendMessage_vssn(gameObject, func, param);
    15.     } else
    16.         throw "" + param + " is does not have a type which is supported by SendMessage.";
    17. }
    then we will get absolutely different result:
    Screen Shot 2016-01-29 at 21.41.59.png

    I think this can be easily added to the release in the near future. Feel free to experiment with it, maybe you will be able to optimize the SendMessage even further. And thanks again for a great discovery!
     
  3. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    Hi alex,

    this looks really good! Your improvement kicks ass, because it's very beneficial for everyone using SendMessage without them having to change any code. Would be cool to have this in a next release.

    In the meantime I'll pursue the concept of calling custom C functions. I'll host the thing on GitHub very soon.
    I didn't even knew cwrap before, so I tried it on my callback as well via the "established" 10k call test and it got 4-5 times faster. We're talking about a 99% speed improvement now (instead of the ~96,6% I measured in my first post). That's beyond my exceptions, nice.

    edit:
    The difference gets even more noticeable if you disable exception handling (which we should anyways).
     
    Last edited: Jan 30, 2016
  4. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    As you can see, with proper optimization SendMessage can be almost as efficient as the direct call. These two approaches are however different in nature. SendMessage can be used to call a method of a dynamically created object, referenced by its symbolic name. It therefore has to first resolve the symbolic name to perform the call. And with all the efficient caching involved here, it still has to check if the referenced object exist and is active. When dealing with game objects, this functionality can be very useful.

    On the other hand, if you are handling the call with c/c++, then all this object oriented overhead may become unnecessary for you, so it might be more efficient to just use the direct call. Note that you do not have to adjust the Emscripten command line to export a function. Instead you can just use EMSCRIPTEN_KEEPALIVE macro in the function declaration:
    Code (c):
    1. #include "emscripten.h"
    2. void EMSCRIPTEN_KEEPALIVE call_callback() {
    3.   ...
    4. }
    The function will then get exported automatically (https://kripken.github.io/emscripte...ence/emscripten.h.html#c.EMSCRIPTEN_KEEPALIVE).

    By the way, talking about the SendMessage optimization, you are able to perform this even in the current version of Unity. All you have to do is to override the existing SendMessage implementation with your own. You can do this directly from the index.html by adding, for example, a onRuntimeInitialized handler to the Module object:
    Code (html):
    1. ...
    2. <script src="Release/UnityLoader.js"></script>
    3. <script>
    4.   Module.onRuntimeInitialized = function() {
    5.     SendMessage = function(gameObject, func, param) {
    6.       // your implementation
    7.     }
    8.   }
    9. </script>
    10. ...
    Now you can just add this code to the index.html template (http://docs.unity3d.com/Manual/webgl-templates.html) so that it will be automatically added to the index.html each time you rebuild your project, for example:
    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.     <p class="header"><span>Unity WebGL Player | </span>%UNITY_WEB_NAME%</p>
    13.     <div class="template-wrap clear">
    14.       <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" height="%UNITY_HEIGHT%px" width="%UNITY_WIDTH%px"></canvas>
    15.       <br>
    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.     <p class="footer">&laquo; created with <a href="http://unity3d.com/" title="Go to unity3d.com">Unity</a> &raquo;</p>
    21.     %UNITY_WEBGL_LOADER_GLUE%
    22.  
    23.     <script>
    24.       Module.onRuntimeInitialized = function() {
    25.         SendMessage = function(gameObject, func, param) {
    26.           if (param === undefined) {
    27.             if (typeof this.SendMessage_vss != 'function')
    28.               this.SendMessage_vss = Module.cwrap('SendMessage', 'void', ['string', 'string']);
    29.             this.SendMessage_vss(gameObject, func);
    30.           } else if (typeof param === "string") {
    31.             if (typeof this.SendMessage_vsss != 'function')
    32.               this.SendMessage_vsss = Module.cwrap('SendMessageString', 'void', ['string', 'string', 'string']);
    33.             this.SendMessage_vsss(gameObject, func, param);
    34.           } else if (typeof param === "number") {
    35.             if (typeof this.SendMessage_vssn != 'function')
    36.               this.SendMessage_vssn = Module.cwrap('SendMessageFloat', 'void', ['string', 'string', 'number']);
    37.             this.SendMessage_vssn(gameObject, func, param);
    38.           } else
    39.               throw "" + param + " is does not have a type which is supported by SendMessage.";
    40.         }
    41.       };
    42.     </script>
    43.  
    44.   </body>
    45. </html>
     
    prestonmatterport likes this.
  5. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    Hi alex,

    that's a lot of useful hints again! I'll give them a run later, thanks!

    You're right, comparing a cwrap calls of static methods with the SendMessage mechanism isn't fair/meaningful since SM is more than a simple call. I still did it because I don't need the SM overhead in my particular project, but still had/have to deal with the additional delay it created. So yeah, SendMessage is still useful for some cases. I may remove those comparing test or at least document that/why they're not fair.

    edit: did it!
     
    Last edited: Jan 30, 2016
  6. dansav

    dansav

    Joined:
    Sep 22, 2005
    Posts:
    406
    Is there any way to call my own unity functions directly from webGL javascript using cwrap or _(underscore) and some compiler directive like the keepalive directive mentioned above? Maybe some combination of the two techniques?

    I've tried some experiments using cwrap, and _(underscore) calling a function I create but they all fail with a message
    about not being able to find the function because it was probably removed.

    in unity c#
    int int_sqrt(int x){
    return(x*x);
    }
    in unityscript
    function int_sqrt(x:int){
    return x*x
    }

    If I try to use the Emscripten_KeepAlive directive you mentioned above. I get errors such as wrong preprocessor directive, unexpected int, Emscripten_KeepAlive cannot find directive.

    in unity c#
    #include emscripten.h
    int EMSCRIPTEN_KEEPALIVE int_sqrt(intx){
    return(x*x);
    }

     
    Last edited: Mar 26, 2016
  7. dansav

    dansav

    Joined:
    Sep 22, 2005
    Posts:
    406
    @atti
    Your results are amazing and exactly what I need, but I'm not sure I understand how to implement your discovery for my example. I've done mostly unityscript programming. My knowledge of c++ and c# extends only to modifying other people's plugins so I'm pretty confused conceptually about how it works.
     
  8. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    In the first post there's the github link to the demo project. have you tried running it?
    You then basically have to port the C# parts to UnityScript, if you insist, but I have no clew how this is done in detail since I don't use it at all.
     
  9. dansav

    dansav

    Joined:
    Sep 22, 2005
    Posts:
    406
    I tried the project. As I understand it, you basically communicate very quickly from javascript to the plugin because you kept_alive your c++ functions when they were compiled so they are visible by direct communication. You also implemented callbacks for several data types and it's very fast.

    I want to communicate directly from javascript to unity functions I've already created. For example, I can create a C# function that will return the velocity.x of a gameObject. My goal would be to call that function from javascript and get a return value back to javascript. If I call the plugin from javascript, would the plugin call the C# function and then return a value back to the plugin which would then return it to javascript?
     
  10. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    That's how I did it and how I know it should work. Calling C# directly is theoretically possible, but you would have to reverse engineer the C++ code generated by IL2CPP, which is probably hard, maybe not possible without Unity's help.
     
  11. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Hello dansav.

    atti is right. C# code is not compiled into JavaScript directly. First, il2cpp is used to generate C++ code for your scripts, and only then this generated C++ code is compiled into JavaScript. Even if you preserve your C# function from stripping and name mangling and manage to export it from the module somehow, you still should not rely on its intermediate il2cpp-generated C++ implementation. On the other hand, C plugin will be compiled into JavaScript directly, so you will have full control of the process this way (note that EMSCRIPTEN_KEEPALIVE macro only applies to C/C++ code).

    If I understand correctly, you are planning to perform a computation which requires interleaved C#/JavaScript code execution. Note that in many cases it is also possible to restructure the code in such a way that it will be not JavaScript code calling C# functions, but rather C# code calling JavaScript functions (which would be much easier to implement). Of course this does not apply to the cases where asynchronous JavaScript operations are involved.
     
  12. dansav

    dansav

    Joined:
    Sep 22, 2005
    Posts:
    406
    Thanks for the information. Is atti's solution only feasible for C# or would it also work in UnityScript?
     
  13. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Not completely sure at the moment if this solution applies to UnityScript, this should be double checked, but before you start using this scheme, you might want to consider possible alternatives.

    Note that in JavaScript you do not have the game object reference, but rather the game object symbolic name. This is exactly the reason why direct call to a static C function can be faster than SendMessage, as SendMessage has to first resolve the symbolic name and check if the found object is active. Therefore if you are planning to use symbolic object names in your JavaScript, you might not get much higher performance than usual SendMessage, unless you implement your own caching mechanism.

    Although SendMessage does not return the result of your computation back to JavaScript, you can still transfer this result to JavaScript explicitly using a helper JavaScript function. Consider the following example:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Runtime.InteropServices;
    4.  
    5. public class Cube : MonoBehaviour {
    6.    [DllImport("__Internal")]
    7.    private static extern void CubeComputation();
    8.    [DllImport("__Internal")]
    9.    private static extern void SetCubePosition (float x, float y, float z);
    10.  
    11.    void SendPositionToJavaScript() {
    12.      SetCubePosition (transform.position.x, transform.position.y, transform.position.z);
    13.    }
    14.  
    15.    void OnMouseDown() {
    16.      CubeComputation ();
    17.    }
    18.  
    19.    void Update() {
    20.      transform.position = new Vector3 (Mathf.Sin (Time.time), Mathf.Cos (Time.time), 0);
    21.    }
    22. }
    and the accompanying JavaScript plugin:
    Code (JavaScript):
    1. var CubePlugin = {
    2.   CubeComputation: function() {
    3.     SendMessage('Cube', 'SendPositionToJavaScript');
    4.     alert('Cube position is (' + _CubeComputation.x + ',' + _CubeComputation.y + ',' + _CubeComputation.z + ')');
    5.   },
    6.   SetCubePosition: function(x, y, z) {
    7.     _CubeComputation.x = x; _CubeComputation.y = y; _CubeComputation.z = z;
    8.   }
    9. };
    10. mergeInto(LibraryManager.library, CubePlugin);
    In this example CubeComputation JavaScript function is calling SendPositionToJavaScript C# method of the Cube game object, which is using helper SetCubePosition JavaScript function to store the result of the computation in the _CubeComputation JavaScript object, and this result (explicitly sent from C#) will be available to the CubeComputation function right after the SendMessage returns. This is of course not as compact as getting result from SendMessage directly, but it is functionally equivalent. Note that I have been using _CubeComputation JavaScript object to store the intermediate result, because this is what the CubeComputation plugin function will be compiled into, but you can also use any other JavaScript object to store the context of the computation. This solution is also not thread safe, but this should not be a problem at the moment, as JavaScript is currently single threaded.
     
    Last edited: Mar 29, 2016
  14. dansav

    dansav

    Joined:
    Sep 22, 2005
    Posts:
    406
    It looks like CubeComputation takes no variables, but then you are adding x,y,z objects to the function itself to store the output? and this output would be available on the webgl webpage javascript. Could you do the same thing with ExternalEval without the plugin. Application.ExternalEval(CubeComputation.x=x;CubeComputation.y=y;CubeComputation.z=z)?
     
  15. dansav

    dansav

    Joined:
    Sep 22, 2005
    Posts:
    406
    SendMessage says there is "no receiver" available when using a large string. As soon as I set the string size to a smaller string it amount it works again. I think in my experiment it was about above 200,000 characters when it started giving the "nor receiver" error. Is there a character limitation on SendMessage?
     
  16. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    .
    It does not really matter which JavaScript object you are using to store the result. For example, you can store the result in window.CubeComputationX = x. Or you can create your own global JavaScript object like var MyResult = {} in advance and then use MyResult.x = x. It will work pretty much the same way. So I just used the _CubeComputation object as an already existing namespace, not to mess with global variables and not to create additional objects (note that in JavaScript functions are in fact objects and can have properties).

    I think Application.ExternalEval should work the same way, just you should use ExternalEval wisely, as it may imply security restriction in some cases (i.e. in Chrome packaged app).
     
    Last edited: Mar 30, 2016
  17. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    I guess I am not aware of such limitation, except the module stack size limit (which is proportional to the total module memory size and should be around a few megabytes), but I can check on this.
    Normally, if you want to transfer large amount of data (i.e. a file) from JavaScript to WebGL application, you can either allocate the data in the global module memory using _malloc (this way you will not be limited by the module stack) and return the string address from the jslib plugin function. Or you can also create a blob in JavaScript, send it's url to WebGL application using SendMessage, and then download it using WWW request.
     
  18. dansav

    dansav

    Joined:
    Sep 22, 2005
    Posts:
    406
    Thanks for the easy to understand and comprehensive explanations about how things work.

    I've been trying to send an array of floats back and forth. I'm converting them to a string and back again. The conversions barely take any time at all, but sending it back and forth using SendMessage is really slow, as the string gets 10x larger it becomes 10 times slower to pass back and forth. atti's solution is about the same speed as your SendMessage speedup. Is there some shared memory that both the webgl webpage javascript and UnityScript could both access?
     
  19. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Yes, of course. You can interact with the WebGL application memory directly from JavaScript. Use the http://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html to check on the basics (especially PrintFloatArray function seems to be related to your use case). For example, you can allocate a float array in C#, send it's address to JavaScript (which is in fact just an offset on the module heap), and reuse this array in subsequent computations. Just make sure that C# array does not get garbage collected, and also when the array is destroyed, you should notify JavaScript that the heap offset is no longer valid. Or, to be completely safe, you can just reallocate a new array for each interaction with JavaScript, and destroy it after interaction is complete.
     
  20. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    I guess this question is out of the scope of the current discussion, as this thread is mainly about non-standard ways of communication. I believe in your case the standard approach should be sufficient. Could you please create a new thread and move your last question there?
     
  21. intentionperception

    intentionperception

    Joined:
    Jun 13, 2016
    Posts:
    13
    This doc page suggests that a SendMessage call can be made at any time after index.html finishes interpreting JS (in a WebGL build):

    https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html

    Yet, if I wait for a WebGL Release to finish building, copy all assets to an http server, load its index.html, and then open Chrome Dev Tools console and call SendMessage -- without calling it on a specific object -- then I get an error that it's undefined. There seems to be an unspoken requirement, perhaps related to the Module definition.
     
  22. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    You're right, that the runtime is not ready if you call SendMessage right away, but Emscripten gives you some options here:
    https://kripken.github.io/emscripte...ded-and-it-is-safe-to-call-compiled-functions

    Look at my example project:
    https://github.com/atteneder/UnityJavascriptInteraction

    right after the unity glue code (look at the template's index.html), I include test.js with basically this piece of code:
    Code (JavaScript):
    1. Module.onRuntimeInitialized = function() {
    2. console.log('Unity is ready now');
    3. }
    4.  
    hth,
    atti
     
    intentionperception likes this.
  23. intentionperception

    intentionperception

    Joined:
    Jun 13, 2016
    Posts:
    13
    Your project solved my problem, thanks!

    Some tips for others who use it:
    1. Let's assume you want to use just one of atti's methods, say, the one for passing json as a string from the html container to the game object. You'd call "c_vxjson" from the html container (see test.js) and this will be received by TargetVxJson in the game object (see Receiver.cs)
    2. You can rename test.js (and update the filename in index.html) but inside of it do not remove any of the entries in Module.onRuntimeInitialized. I replaced everything else with a fn named "onGameReady" (containing the call to c_vxjson), and updated progress.js to call this fn instead of run_tests.
      1. Renaming "c_vv3json" also gave me a problem once, so I reverted that.
    3. Do not alter anything in Receiver.cs either, except the content of the fn you want to use. In the case of TargetVxJson, you may also want to rename the struct it uses for json deserialization (I made it a class with subclasses as well).
    4. You'll want to use Receiver.cs as a script for the game object you want to control from the html container. I haven't gotten this far yet but I expect it to work. I also don't know whether it's possible to dispatch commands to different game objects that each have their own script; I suspect Receiver.cs would need to be adapted to control other game objects even though it's attached to just one.
     
  24. hum8

    hum8

    Joined:
    Apr 18, 2013
    Posts:
    23
    Hi, I tried your code hoping to solve javascript - webgl unity communication, but, after building from your repository code, I get this error when loading index.html:

    ReferenceError: Can't find variable: Module

    I'm on Unity 5.6 beta, and Safari on Mac (same result with Chrome, tough).

    Do you have an idea of what might cause the error?

    Thanks!
     
  25. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    Yes, when I tested 5.6 I noticed they renamed "Module". Can't remember exactly, but something like "GameInstance".
    Have a look into UnityLoader.js to see exactly or your browser's dev console.

    hth
     
  26. hum8

    hum8

    Joined:
    Apr 18, 2013
    Posts:
    23
    Pardon my lack of knowledge ... what should I look for, exactly? What was "Module" before?
     
  27. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    I looked a test I did some weeks ago. Just add this at the top of tests.js:

    Code (JavaScript):
    1. if(!window.Module) {
    2.     window.Module = gameInstance.Module;
    3. }
    Module is now inside another object.
     
  28. hum8

    hum8

    Joined:
    Apr 18, 2013
    Posts:
    23
    it now says: "ReferenceError: Can't find variable: gameInstance"

    This is the index.html generated by your project:

    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 | JavascriptInteraction</title>
    7.     <script src="progress.js"></script>
    8.     <style>
    9.     /* a style sheet needs to be present for cursor hiding and custom cursors to work. */
    10.     </style>
    11.   </head>
    12.   <body>
    13.     <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" height="200px" width="320px"></canvas>
    14.     %UNITY_WEBGL_LOADER_GLUE%
    15.     <script src="tests.js"></script>
    16.   </body>
    17. </html>
    Should't be somewhere a <script src="Build/UnityLoader.js"/> ?

    Edit: wait a minute, %UNITY_WEBGL_LOADER_GLUE% shouldn't be in index.html in the WebGL build .. so something went wrong when I built the WebGL

    p.s. I have 5.6 beta9
     
    Last edited: Mar 2, 2017
  29. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    Last edited: Mar 10, 2017
  30. deniskrop

    deniskrop

    Joined:
    Dec 6, 2014
    Posts:
    25
  31. atti

    atti

    Joined:
    Feb 22, 2011
    Posts:
    70
    After a quick look: I think not.
    My demo is fast because it's an alternative to SendMessage. The WebSockets plugin doesn't use SendMessage in first place.
    For example receiving (huge chunks of) data: Seems like they cache responses in WebSocket.jslib (socket.messages.push(array)) and poll them from C# via SocketRecv, which directly writes into the heap.
    Now you *could* theoretically invoke a native cwrapped C# function when a message is received (via socket.socket.onmessage), and pass on the content as parameter. But this is probably dangerous, since you cannot know in what state Unity is within its run-loop. So you'd have to synchronize things in C# again.

    My gut tells me it probably cannot get much faster, but feel free to prove me wrong.
     
    swdenis likes this.
  32. swdenis

    swdenis

    Joined:
    Aug 5, 2016
    Posts:
    1
    Thanks atti, I have a multiplayer webgl game and some users have experiencing a major delay with what they should be seeing, not sure where the problem is stemming from exactly.
     
  33. mehul-24

    mehul-24

    Joined:
    Jul 9, 2015
    Posts:
    2
    Does anyone know if there a unity version/patch which included the send message change? Or do i have to still add this to my template?


    Code (JavaScript):
    1. Module.onRuntimeInitialized = function() {
    2.         SendMessage = function(gameObject, func, param) {
    3.           if (param === undefined) {
    4.             if (typeof this.SendMessage_vss != 'function')
    5.               this.SendMessage_vss = Module.cwrap('SendMessage', 'void', ['string', 'string']);
    6.             this.SendMessage_vss(gameObject, func);
    7.           } else if (typeof param === "string") {
    8.             if (typeof this.SendMessage_vsss != 'function')
    9.               this.SendMessage_vsss = Module.cwrap('SendMessageString', 'void', ['string', 'string', 'string']);
    10.             this.SendMessage_vsss(gameObject, func, param);
    11.           } else if (typeof param === "number") {
    12.             if (typeof this.SendMessage_vssn != 'function')
    13.               this.SendMessage_vssn = Module.cwrap('SendMessageFloat', 'void', ['string', 'string', 'number']);
    14.             this.SendMessage_vssn(gameObject, func, param);
    15.           } else
    16.               throw "" + param + " is does not have a type which is supported by SendMessage.";
    17.         }
    18.       };