Consideraciones de Memoria cuando tenga como objetivo WebGL
Utilizando plantillas WebGL

WebGL: Interactuando con scripting del navegador

Cuando construya contenidos para la web, usted podría necesitar comunicarse con otros elementos en su página web. O usted podría querer implementar funcionalidad utilizando Web APIs las cuales Unity actualmente no expone por defecto. En ambos casos, usted necesita directamente interactuar con el motor JavaScript del navegador. Unity WebGL proporciona diferentes métodos para hacer esto.

Llamando código JavaScript desde Unity

El primero es lo mismo que para el Web Player. Usted puede utilizar las funciones Application.ExternalCall() y Application.ExternalEval() para invocar el código JavaScript en la página web embebida. Para llamar métodos en GameObjects en su contenido desde el JavaScript de su navegador, usted puede utilizar el siguiente código:

SendMessage ('MyGameObject', 'MyFunction', 'foobar');

Llamando funciones JavaScript desde un plugin

La otra manera para utilizar JavaScript del navegador en su proyecto es agregar sus fuentes de JavaScript a su proyecto, y luego llamar esas funciones directamente desde su código script. Para hacer esto, coloque los archivos con código Javascript utilizando la extensión .jslib (ya que la .js normal sería cogida por el compilador de UnityScript) a una carpeta “Plugins/WebGL” en su carpeta Assets. El archivo necesita tener una sintaxis como esta:

Assets/Plugins/WebGL/MyPlugin.jslib

var MyPlugin = {
    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]);
    }
};

mergeInto(LibraryManager.library, MyPlugin);

Luego usted llama estas funciones desde sus scripts C# así:

using UnityEngine;
using System.Runtime.InteropServices;

public class NewBehaviourScript : MonoBehaviour {

    [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());
    }
}

Tipos numéricos simples se pueden pasar a JavaScript en parámetros de funciones sin requerir conversión. Otros tipos de datos serán pasados como apuntadores en el heap emscripten (el cual es simplemente un gran arreglo en JavaScript). Para Strings, usted puede utilizar la función de ayuda Pointer_stringify para convertirle en un string JavaScript. Para devolver un valor string usted necesita llamar _malloc para asignar algo de memoria y luego la función de ayuda writeStringToMemory para escribir un string de JavaScript a esta. Si el string es un valor de retorno, entonces el tiempo de ejecución il2cpp se encargará de liberar la memoria para usted. Para arreglos que tengan tipos primitivos, emscripten proporciona diferentes ArrayBufferViews a su heap para diferentes tamaños de enteres, enteros unsigned o representaciones punto flotantes de memoria: HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64. Para acceder a una textura en WebGL, emscripten proporciona el arreglo GL.textures que mapea IDs de textura nativo desde Unity a objetos texture de WebGL. Las funciones WebGL serán llamadas en el contexto de WebGL de emscripten, GLctx.

Llamando funciones C++ desde un plugin

Debido a que Unity compila sus fuentes a JavaScript desde código C++ utilizando emscripten, usted también puede escribir plugins en código C o C++, y llamar estas funciones desde C#. Entonces, en vez del archivo jslib en el ejemplo de arriba, usted puede tener un archivo c como el de abajo en su proyecto - este será automáticamente compilado con sus scripts, y usted podrá llamar funciones de este, como cualquier otro ejemplo de JavaScript de arriba.

Si usted está utilizando C++ (.cpp) para implementar el plugin entonces usted debe asegurarse que las funciones están declaradas con un c linkage para evitar problemas de manejo de nombres.

Assets/Plugins/WebGL/MyPlugin.c

#include <stdio.h>

void Hello ()
{
    printf("Hello, world!\n");
}

int AddNumbers (int x, int y)
{
    return x + y;
}

Personalizando Revisiones de Compatibilidad o Manejadores de Errores

Unity va a escribir algo de código JavaScipt a las construcciones por defecto, el cual va a revisar por compatibilidad de plataforma y errores de manejo. Este código va a mostrar errores de advertencia cuando corra en plataformas sin soportar, como cuando se intente correr contenido de Unity WebGL en dispositivos móviles. También va a parse strings de error y excepción del navegador, para revisar por errores conocidos y mostrar diálogos de error con mensajes de error más compresivos.

Usted puede personalizar este manejo, por ejemplo, si usted quiere suprimir los mensajes de error cuando corra en dispositivos móviles. Para hacer esto, abra el index.html generado, y remplace este código con las implementaciones de funciones JavaScript actuales para el manejo de errores y/o revisiones de compatibilidad:

  var Module = {
    TOTAL_MEMORY: 268435456,
    errorhandler: null,
    compatibilitycheck: null,
  };

La función compatibilitycheck será llamada al inicio, y usted puede colocar cualquier código aquí para mostrar mensajes cuando usted detecte que el contenido no es soportado.

La función errorhandler será llamada cuando la página invoque su manejador de eventos window.onerror, y utiliza los mismos parámetros. Devuelva “true” de esta función para resumir su ejecución, y “false” para pasar el error al manejador por defecto de errores de Unity.

Example:

  var Module = {
    TOTAL_MEMORY: 268435456,
    errorhandler: function(err, url, line) {
        alert("error " + err + " occurred at line " + line);

        // return true so Unity's error handler is not executed.
        return true;
    },
    compatibilitycheck: function() {
        // check compatibility ...
    }
  };
Consideraciones de Memoria cuando tenga como objetivo WebGL
Utilizando plantillas WebGL