Search Unity

WEBGL: return value from javascript function

Discussion in 'Scripting' started by Cyrille_O, Aug 1, 2017.

  1. Cyrille_O

    Cyrille_O

    Joined:
    Jul 12, 2016
    Posts:
    9
    Hi,
    First of all : I'm newbie with WebGL and just junior on javascript ... :-(

    I would like to retrieve data from javascript functions. A Json would be perfect but a big string could be helpfull.
    I saw a post about it :
    https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html

    it says :
    "To return a string value you need to call _malloc_ to allocate some memory and the writeStringToMemory helper function to write a JavaScript string to it"

    But I can not find a way to have the Malloc function alvailable in javascript ...
    Could someone give me more info or much better : an example....

    Thank you in advance for you help

    Cyrille
     
  2. RoMax92

    RoMax92

    Joined:
    May 29, 2017
    Posts:
    135
    I start using Unity Web GL since few weeks, and i move to another engine: the build is very slow and weight, unfortunatelly.
    I try PlayCanvas, and it's much better for web games, trust me.

    Anyway, if you can post some code where find a mistake, it's easier to fix ;D
     
    ENOUGH- likes this.
  3. Cyrille_O

    Cyrille_O

    Joined:
    Jul 12, 2016
    Posts:
    9
    PlayCanvas looks great, but I need to build on Windows as well as with WebGL, is that possible ?
    what is the learning curve ?
    I try to launch some games from the site but I everytime get the rrror message "site unreachable"... :-(

    here is my first code trying to use malloc in a javascript function :

    function test(){
    MyString = "0132456789";
    var buffer = _malloc(lengthBytesUTF8(MyString) + 1);
    writeStringToMemory(MyString, buffer);
    return buffer;
    }
     
  4. RoMax92

    RoMax92

    Joined:
    May 29, 2017
    Posts:
    135
    yeah, PlayCanvas build in Web GL
    If you know something in C#, you will learn JavaScript very fast.
    Depends of the server, you need in any case to export the build with the compress formatt in Gzip, and if you have server based on Linux or Windows you need some autorization.
    Here is explained very well: https://docs.unity3d.com/Manual/webgl-deploying.html
     
  5. Cyrille_O

    Cyrille_O

    Joined:
    Jul 12, 2016
    Posts:
    9
    is there someone having an idea other than changing development tools ?
     
  6. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    If you're working directly from that example code in the docs, then you've created a jslib file in the Plugins folder for your javascript functions, correct?

    Then you create a complementary cs file which contains the static extern definitions of those functions for use in Unity scripting.
     
  7. Cyrille_O

    Cyrille_O

    Joined:
    Jul 12, 2016
    Posts:
    9
    hi,
    sorry for the delay, I was in holidays....

    I did as you say, like it was explain in the docs, but I get the following error message :

    EntryPointNotFoundException: Hello
    MainScript.Start () (at Assets/MainScript.cs:30)

    I google it but was unable to find any answer...
     
  8. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Would you mind posting your jslib code, and the .cs file function definitions, and also your MainScript code that tries to use it?

    Make sure you've got that jslib in the plugins directory.
     
  9. Cyrille_O

    Cyrille_O

    Joined:
    Jul 12, 2016
    Posts:
    9
    I just have 2 files :


    ********************Assets/Plugins/WebGL/MyPlugin.jslib :

    mergeInto(LibraryManager.library, {

    Hello: function () {
    window.alert("Hello, world!");
    },

    HelloString: function (str) {
    window.alert(Pointer_stringify(str));
    },

    PrintFloatArray: function (array, size) {
    for(var i = 0; i < size; i++)
    console.log(HEAPF32[(array >> 2) + size]);
    },

    AddNumbers: function (x, y) {
    return x + y;
    },

    StringReturnValueFunction: function () {
    var returnStr = "bla";
    var buffer = _malloc(lengthBytesUTF8(returnStr) + 1);
    writeStringToMemory(returnStr, buffer);
    return buffer;
    },

    BindWebGLTexture: function (texture) {
    GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[texture]);
    },

    });

    ********************Assets/ MainScript.cs :
    using UnityEngine;
    using System.Runtime.InteropServices;




    public class MainScript : MonoBehaviour {

    public GameObject cube;
    public Vector3 currentPos;
    [DllImport("__Internal")]
    private static extern void Hello();

    [DllImport("__Internal")]
    private static extern void HelloString(string str);

    [DllImport("__Internal")]
    private static extern void PrintFloatArray(float[] array, int size);

    [DllImport("__Internal")]
    private static extern int AddNumbers(int x, int y);

    [DllImport("__Internal")]
    private static extern string StringReturnValueFunction();

    [DllImport("__Internal")]
    private static extern void BindWebGLTexture(int texture);

    void Start() {
    Hello();

    HelloString("This is a string.");

    float[] myArray = new float[10];
    PrintFloatArray(myArray, myArray.Length);

    int result = AddNumbers(5, 7);
    Debug.Log(result);

    Debug.Log(StringReturnValueFunction());

    var texture = new Texture2D(0, 0, TextureFormat.ARGB32, false);
    BindWebGLTexture(texture.GetNativeTextureID());
    }
    }
     
    StarArcher likes this.
  10. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Please include code tags when pasting snippets of code, it makes it much more readable.

    In the editor, select your .jslib file in your plugins folder, and verify it has platforms selected in the inspector.
     
    LilGames likes this.
  11. Cyrille_O

    Cyrille_O

    Joined:
    Jul 12, 2016
    Posts:
    9
    ok for code tags, I will use it for futur post....
    for the JSLIB, The only platforms selected is 'WebGL'
     
  12. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Are you seeing these errors when playing a WebGL build, or playing in the editor? If you try to play in the editor, these functions will fail because the plugin is WebGL-specific.

    You can try to wrap your functions so they don't get called while in the editor:
    Code (CSharp):
    1. #if UNITY_WEBGL
    2. Hello();
    3. #endif
     
    LilGames likes this.
  13. Cyrille_O

    Cyrille_O

    Joined:
    Jul 12, 2016
    Posts:
    9
    I get this error in the editor...

    you mean I should build the project to have this functions working ?
    It won't be very easy to use then, the build process take long to complete.... :-(

    I need to query a database to retrieve data and send it to Unity through JSON, is that wat the best one ?
    or can you advice me an other architecture ?
     
  14. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    These jslib functions can only work in a web browser context, not in the editor.

    If you just need to send/retrieve data, you can use the www class or UnityWebRequest.
     
  15. lakhbir

    lakhbir

    Joined:
    May 15, 2015
    Posts:
    15


    this will work when you host to the web server. Not working on editor.
     
  16. JustinTheSwift

    JustinTheSwift

    Joined:
    Feb 4, 2017
    Posts:
    5
    While this thread correctly explains that the javascript plugin will not work in the game editor, it doesn't answer the underlying question: How do we use malloc to return a string? In the years since this thread started, the instructions have been updated to say "To return a string value you need to call _malloc to allocate some memory and the stringToUTF8 helper function to write a JavaScript string to it. If the string is a return value, then the il2cpp
    runtime will take care of freeing the memory for you." (https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html), but that doesn't give us a code sample. Very frustrating.
     
  17. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,092
    The code example is actually right there on the page you linked.

    One of the things they have in their JSLib is this function:

    Code (CSharp):
    1. StringReturnValueFunction: function () {
    2.     var returnStr = "bla";
    3.     var bufferSize = lengthBytesUTF8(returnStr) + 1;
    4.     var buffer = _malloc(bufferSize);
    5.     stringToUTF8(returnStr, buffer, bufferSize);
    6.     return buffer;
    7.   }
    And they call it from C# in the second code block.

    by declaring:
    [DllImport("__Internal")]
    private static extern string StringReturnValueFunction();


    and calling the function in
    Start() => Debug.Log(StringReturnValueFunction());


    The declaration is the same function name as defined in the JSLib but marked with a DllImport attribute.