Search Unity

SendMessage doesn't work on 5.6 for WebGL?

Discussion in 'Web' started by hydrix, Jan 19, 2017.

  1. hydrix

    hydrix

    Joined:
    Apr 30, 2016
    Posts:
    10
    I just tried building on both 5.5 and 5.6, and in 5.6 my SendMessage from the Javascript side gives a reference exception with the exact same code.
    As a test I put a SendMessage a looping script in Javascript:

    setInterval(function() {
    SendMessage("MyObject", "MyFunction", "testdata");

    },3000);




    On the 5.5 build it gives a reference exception until the game loads, at which point it stops giving any errors.
    On the 5.6 build it gives a reference exception even after the game loads as long as the loop runs.


    Can anybody confirm that Javascript SendMessage is working for them on 5.6?
     
  2. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Hello hydrix.

    In Unity 5.6 we are using a new embedding scheme, which allows to embed a properly namespaced WebGL build on an arbitrary page without conflicting with the main page code. For example, now you should also be able to embed multiple builds on the same page. For this reason global SendMessage does not make sense anymore, and you should explicitly specify the instance of the game you are sending your message to.

    Each game instance has it's own SendMessage method (as well as SetFullscreen method). The JavaScript code in the html might look like:
    Code (JavaScript):
    1. var gameInstance = UnityLoader.instantiate("gameContainer", "Build/mybuild.json", {onProgress: UnityProgress});
    2. setTimeout(function () {gameInstance.SendMessage("MyObject", "MyFunction", "testData");}, 3000);
    Note that you only need to use this external game instance API when you send a message to your game from the global JavaScript namespace. If you are using SendMessage function in a JavaScript plugin included in your project, then the plugin code will be executed inside the corresponding Module namespace, so you can call SendMessage function from your JavaScript plugin directly without using external API.

    P.S. There has been a small issue in early 5.6 betas, where API was declared as .sendMessage instead of .SendMessage. This should be fixed now and both .SendMessage and .SetFullscreen game instance methods should start with a capital letter.

    P.S. If you want to avoid the reference exception which is thrown in your case while the game is still loading, you can override the onRuntimeInitialized Module method directly from the html using additional embedding parameter, it will notify the embedding page about the module being ready to receive messages.

    The documentation will be updated in the near future. Let me know if this helps.
     
  3. Handsome-Wisely

    Handsome-Wisely

    Joined:
    Mar 20, 2013
    Posts:
    102
    i also want to use send message from html to unity web gl. but failed! can you give me a example, such as where put the function and how to set param. my code like this:
    Code (JavaScript):
    1.     <script type='text/javascript'>
    2.   var Module = {
    3.     TOTAL_MEMORY: 33554432,
    4.     errorhandler: null,            // arguments: err, url, line. This function must return 'true' if the error is handled, otherwise 'false'
    5.     compatibilitycheck: null,
    6.     dataUrl: "Release/ROOT.data",
    7.     codeUrl: "Release/ROOT.js",
    8.     memUrl: "Release/ROOT.mem",
    9.   };
    10.    var gameInstance = UnityLoader.instantiate("gameContainer", "Build/mybuild.json", {onProgress: UnityProgress});
    11.    setTimeout(function () { gameInstance.SendMessage("IHtml", "Gry", "testData"); }, 3000);
    12. </script>
    13. <script src="Release/UnityLoader.js"></script>
    and i still can not sendmessage suceessfully!

    thank you!
     
  4. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Hello Handsome-Wisely.

    SendMessage mechanism in 5.6 is different from previous versions of Unity, because staring from 5.6 all the build code is isolated from the main page code. Considering that you have "var Module = {}" in your code, it seems that you are using Unity version below 5.6, in which case direct call to SendMessage() should do the job.
     
  5. nsmith1024

    nsmith1024

    Joined:
    Mar 18, 2014
    Posts:
    870
    Great, so all my Javascript code is broken now!

    It would be great if we didnt have to change anything, and it defaulted to old way if there was only a single instance of WebGL on the page, and the multiple instance thing only need when you have multiple instances running on the same page.

    I'm using Version 5.4 i tried upgrading to 5.6 (one of the beta releases) but the builds were 50 meg larger than the 5.4 builds. I also need to use the new video player in 5.6 since the old one cant fast forward or rewind, and sometimes gets stuck playing a video clip for some reason.

    So I have to re-do all the javascript code to use the instancing or else i cant get all the cool stuff on 5.6.
     
    Last edited: Apr 18, 2017
  6. Fizzer

    Fizzer

    Joined:
    Nov 16, 2016
    Posts:
    40
    It's true breaking changes are annoying, but sometimes they're necessary. I'm betting that if you take a step back and examine the new embedding system you'll agree it's far better than the old one, and once you get through the pain of learning the new system and migrating your code to it, you'll be in a better place.

    It sounds like you have a ton of code that calls SendMessage. If so, it should be pretty easily to adapt it by simply defining your own function named SendMessage that just forwards the arguments to gameInstance.SendMessage.
     
  7. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Hello nsmith1024.

    As @Fizzer suggests, if you already have a lot of code using direct calls to SendMessage on your page and you don't want to refactor it, you can simply use the following temporary workaround:
    Code (JavaScript):
    1. SendMessage = gameInstance.SendMessage;
    The idea behind the new embedding scheme is that the page code can be isolated from the build code, so that you can easily embed your build into any page. Previously there was no such possibility, so some developers occasionally mixed the build specific Javascript code with the page code, which now makes is quite difficult to strip that code out of the page.

    If you want to make your build easy to embed on any page, you should consider putting all the build specific code into .jslib and .jspre plugins. Note that Javascript plugins are defined inside the build namespace, so you can use the SendMessage function from there directly.

    If you use the workaround mentioned above, then your redefined SendMessage function will logically belong to the page code, not to the build code. It may be temporary used for compatibility, while you can gradually transfer more and more Javascript code from the page into plugins, which are internal to the build.

    It is also worth mentioning that embedding scheme is not universal. Generally, if you want to namespace the code, then you should also be able to namespace all of its dependencies, which is not always easy to achieve. Consider a case when your build depends on some external Javascript library, which was not designed with namespacing in mind (i.e. is actively using the global namespace). In such case it might be a bit problematic to embed such a build on a page which is already using a different version of the same external library, due to the dependency conflicts in the global namespace. This means that it is actually the used dependency which prevents your build from being easily embedded on an arbitrary page. For this reason, try to minimize such problematic dependencies (note, that it is not uncommon that developers sometimes drag in a huge external library just to use a small function, which could otherwise be simply stripped out from that library).
     
    Last edited: Apr 19, 2017