Skip to content

liugang1014/duktape-unity

 
 

Repository files navigation

logo

a quickjs binding version is under development, it supports more modern javascript features. unity-jsb

中文说明

Build Status

Brief

Integerate duktape (an embedded javascript engine) into unity, you can load and run javascript at runtime.
Typescript is a preferred choice, it provides type checks.

editing script

Features

  • nodejs-like module or browser-like singular js depends on you
  • generate C# to js type binding code, and coresponding d.ts type definition files
  • setTimeout/setInterval/clearTimeout/clearInterval compatible
  • c# delegates
  • optimized unity common valuetypes (Vector2/3,Quaternion,Color...)
  • fixed-point math support (libfixmath)
  • websocket (libwebsockets)
  • iOS (64bit, bitcode)
  • Android (v7a, v8a, x86)
  • remote debugger (vscode)
  • promise (bluebird.js)
  • coroutine (duktape thread)
  • socket (tcp/udp)
  • kcp (not implemented)

You can use lots of pure js libraries in your project, such as protobufjs. protobufjs

Type definition files

The generated d.ts files will improve auto-complete. It will give the information of exposed types from C# and C.

  • delegate type information type definition files
  • generic constraints for out/ref parameter type definition files
  • friendly interface for AddComponent/GetComponent type definition files

Environments

If you use typescript, install typescript at first

npm install -g typescript

Clone

# --depth=1 is highly recommended
git clone https://github.com/ialex32x/duktape-unity --depth=1

Build

prebuilt libraries already in /prebuilt/debug and /prebuilt/release directories.

python/pip/pyyaml is prerequisites.

pip install pyyaml

duktape original source code is at /duktape-/src-input

./configure_duktape.bat # combined duktape source code will be generated 
# at:
# /build/src-debug (with debugger)
# /build/src-release (without debugger)
./make_duktape_<platform>.bat # or ./make_duktape_<platform>.sh in osx

if you build duktape for android in windows, run make_duktape_android.bat in visual studio cross tools commandline (e.g VS2015 x64 ARM Cross Tools Command Prompt).

'./scratch' is a playground for duktape testing in a simple command line app.

./configure_duktape_scratch.bat
./make_duktape_scratch.bat

Sample code

// if your tsconfig.json defined {"module": "commonjs"}, you can 'import' modules like node-js. 

// import module
import { B } from "base/b"
// import module with relative path (. or ..)
import { C } from "./base/c"

class MyPlayer {
    Start() {
        console.log("MyPlayer.Start")
        this.Jump()
    }

    // Update() {
    // }

    Jump() {
        console.log("MyPlayer.Jump")
    }
}

export class A {
    private go: GameObject
    constructor () {
        this.go = new GameObject("test go")
        this.go.transform.localPosition = new Vector3(1, 2, 3) 
        // use Bridge to receive Enable/Disable/Update 
        // don't use the approach a lot, it's better to dispatch futher logic in a single Bridge
        this.go.AddComponent(DuktapeJS.Bridge).SetBridge(new MyPlayer()) 

        let f = new Custom()
        // you can assign function to c# delegate
        f.onopen = function () {
            // ...
        }
        // if you want to register multiple listener, use DuktapeJS.Dispather 
        // you can also use typed Dispatcher generated in _DuktapeDelegates.d.ts, it provides type checks
        f.onload = new DuktapeJS.Dispatcher1<void, string>() 
        f.onload.on(this, this.onload)  // add listener
        f.onload.off(this, this.onload) // remove listener
        f.onload.off(this)              // clear all listeners of this
        f.onload.clear()                // clear all

        // 'out' parameter in c#
        let v = {}
        if (System.Int32.TryParse("123", v)) {
            console.log(v.target)
        }
    }

    private onload(ev: string) {
        let timer1 = setInterval(() => {
            console.log("interval")
        }, 1000)

        setTimeout((a, b) => {
            console.log("timeout", a, b)
            clearInterval(timer1)
        }, 5000, "Arg1", 123)
    }

    square() {
        console.log("A.square")
    }
}

// websocket
let ws = DuktapeJS.WebSocket()
ws.on("open", () => {
    console.log("connected")
    setInterval(() => {
        ws.send("hello, world") // string or buffer 
    }, 1000)
})
ws.on("data", data => {
    console.log("ws receive data", data) // string or buffer (depends on websocket message type you use)
})
ws.on("close", () => {
    console.log("connection lost")
})
ws.connect("ws://127.0.0.1:8080/echo")
setInterval(() => {
    ws.poll()
}, 50)
// http request example
console.log("http requesting...");
HttpRequest.GET("http://t.weather.sojson.com/api/weather/city/101030100", null, (status, res) => {
    console.warn("http response:", status, res);
    if (status) {
        let obj = JSON.parse(res);
        console.log("as object", obj.message);
    }
});
// coroutine example
let co = new Coroutine(function (x) {
    console.log("duktape thread, start:", x);
    for (var i = 1; i <= 5; ++i) {
        let r = Coroutine.yield(i);
        console.log("duktape thread, yield:", r);
    }
    // Coroutine.break();
    return "all done!";
});
let c = 'A'.charCodeAt(0);
while (co.next(String.fromCharCode(c++))) {
    console.log("duktape thread, next:", co.value);
}
console.log("duktape thread, done:", co.value);

Dev status

It's not stable enough, do not use it in production environment.
Vector2/Matrix3x3/Matrix4x4/Quaternion valuetypes optimization is partially written in c, and not fully tested.

Usage

Execute menu item [Duktape -> Generate Bindings] to generate binding code. Typescript source files will be compiled into js after your modification and switch back to Unity Editor.

How to customize exported types

  • duktape.json modify the basic configuration at ./duktape.json (details in Assets/Duktape/Editor/Prefs.cs)
{
    "outDir": "Assets/Generated",
    "typescriptDir": "Assets/Generated",
    "extraExt": "",
    // rootpath of ts/js project
    "workspace": "",
    "logPath": "Temp/duktape.log",
    // auto, cr, lf, crlf
    "newLineStyle": "auto",
    "implicitAssemblies": [
        "UnityEngine",
        "UnityEngine.CoreModule", 
        "UnityEngine.UI", 
        "UnityEngine.UIModule"
    ], 
    "explicitAssemblies": [
        "Assembly-CSharp"
    ],
    // types in blacklist will not be exported
    "typePrefixBlacklist": [
        "JetBrains.",
        "Unity.Collections.",
        "Unity.Jobs.",
        "Unity.Profiling.",
        "UnityEditor.",
        "UnityEditorInternal.",
        "UnityEngineInternal.",
        "UnityEditor.Experimental.",
        "UnityEngine.Experimental.",
        "Unity.IO.LowLevel.",
        "Unity.Burst.",
        // more types ...
        "UnityEngine.Assertions."
    ], 
    "ns": "DuktapeJS",
    "tab": "    "
}
  • implements Duktape.IBindingProcess interface or extends AbstractBindingProcess class
public class MyCustomBinding : AbstractBindingProcess
{
    public override void OnPreCollectTypes(BindingManager bindingManager)
    {
        /*
        bindingManager.AddExportedType(typeof(MyCustomClass));
        bindingManager.TransformType(typeof(MyCustomClass))
            .SetMethodBlocked("AMethodName")
            .SetMethodBlocked("AMethodNameWithParameters", typeof(string), typeof(int))
        */
    }

    public override void OnCleanup(BindingManager bindingManager)
    {
        Debug.Log($"finish @ {DateTime.Now}");
    }
}

Sample scene

Assets/Scenes/main.unity (Sample.cs) demonstrate the basic usage.

Debugger

Support js/ts remote debug.

the libraries in unity project is built with debugger support. if you want to use a release version without debugger support, checkout /prebuilt/release. or compile them by yourself.

debugger

Name: Duktape Debugger
Id: haroldbrenes.duk-debug
Description: Debug Adapter for Duktape runtimes.
Version: 0.5.6
Publisher: HaroldBrenes
VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=HaroldBrenes.duk-debug

If you are debugging ts sources, this extension has some path-resolve issues break the debug process, you can try the modified version.

Referenced libraries

Misc.

About

provide typescript support for unity dynamic scripting

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 50.9%
  • C 21.2%
  • HTML 20.3%
  • Python 2.9%
  • C# 2.8%
  • Makefile 0.4%
  • Other 1.5%