unity3d支持typescript開發


目錄

  1. unity3d支持typescript開發(一)
  2. unity3d支持typescript開發(二)
  3. unity3d支持typescript開發(三)
  4. unity3d支持typescript開發(四)
  5. unity3d支持typescript開發(五)
  6. unity3d支持typescript開發(六)

前言

由於之前的工作是在游戲公司做unity框架,該框架使用的是lua+unity的方案,而最近頻繁接觸typescript后,就有了想要在unity框架內支持typescript的想法.

早期的unity是支持javascript后面簡寫為js的,但是后來被unity拋棄了,其實讓unity支持typescript后面簡寫為ts跟支持lua是很相似的,只需要找到一個可以在.net環境下執行js的解釋器即可,而js可以通過編譯ts來獲得,那么即可支持ts了.

那么此次我們來完成一個示例,首先unity啟動自會后會加載一個prefab,然后加載對應路徑的js代碼並調用onStart方法,該js方法內會調用console.log,而該函數會轉而調用unity內的Debug.Log方法.

.net庫

https://github.com/sebastienros/jint 是比較符合當前條件的.net庫, 但是該庫只提供了基礎的js環境, 而該環境中並不包含console對象.

初始化jint

首先在canvas下添加一個腳本,在該腳本內初始化jint,當Awake方法被觸發的時候,加載prefab, C#代碼如下:

class DemoCanvas : MonoBehaviour
{
    private readonly Engine m_Engine = new Engine();

    private void Awake()
    {
        var prefab = Resources.Load<Component>("demo/Index");
        Instantiate(prefab, this.transform);
    }
}

執行js腳本

由於上文中我們將Jint的初始化代碼放在了Canvas內,因此js腳本的加載執行就不能參考canvas的流程來了,因為Instantiate的時候Awake會被觸發如果這時候要調用Jint.Engine的話則需要將該字段開放,這樣循環引用並不好,因此此處改為在prefab內開放一個方法用於初始化, C#代碼如下:

// js
console.log('hello world');

// C#
class DemoView : MonoBehaviour
{
    public void EvalScript(Engine engine)
    {
        var js = Resources.Load<TextAsset>("demo/index");
        engine.Execute(js.text);
    }
}

// DemoCanvas
public void Awake()
{
    var prefab = Resources.Load<Component>("demo/Index");
    Instantiate(prefab, this.transform).GetComponent<DemoView>().EvalScript(this.m_Engine);
}

運行以后出現了錯誤,這是由於Jint並沒有提供console這個對象,因此需要自己擴展一個console對象.

console對象

閱讀Jint的源碼內我們可以發現,Jint的對象需要繼承自ObjectInstance,然后調用FastAddProperty給該對象添加一個屬性,該方法的定義如下:

public void FastAddProperty(string name, JsValue value, bool writable, bool enumerable, bool configurable)

除了JsValue以外,其他的參數字面上跟js是一致的,這里就不解釋了.由於console.log是一個函數,因此這里JsValue需要使用ClrFunctionInstance,ClrFunctionInstance的定義如下:

public sealed class ClrFunctionInstance : FunctionInstance
{
    public ClrFunctionInstance(Engine engine, Func<JsValue, JsValue[], JsValue> func);
    public ClrFunctionInstance(Engine engine, Func<JsValue, JsValue[], JsValue> func, int length);

    public override JsValue Call(JsValue thisObject, JsValue[] arguments);
}

構造函數中有兩個,其中一個包含了一個int length的參數,因為console.log是不限定參數個數的,因此我們使用另外一個不包含length的構造函數,C#代碼如下:

class ConsoleInstance : ObjectInstance
{
    public ConsoleInstance(Engine engine) : base(engine)
    {
        this.Prototype = engine.Object.Prototype;
        this.FastAddProperty("log", new ClrFunctionInstance(this.Engine, Log), true, false, true);
    }

    public JsValue Log(JsValue thisObject, JsValue[] arguments)
    {
        Debug.Log(arguments[0].ToString());
        return JsValue.Null;
    }
}

// DemoCanvas
public void Awake()
{
    var console = new ConsoleInstance(this.m_Engine)
    {
        Prototype = this.m_Engine.Object.PrototypeObject
    };
    this.m_Engine.SetValue("console", console);

    // 略
}

這里為了簡化log方法內參數的判斷,代碼改為只對第一個值進行ToString的處理.

結尾

到了這里我們就已經完成了unity支持執行js腳本了,但是離支持ts還是有點遠的.由於時間比較零碎,因此其余的部分會在有空的時候繼續提供.如果文章中有任何錯誤或者疑問歡迎提出,如果文章對你有幫助也歡迎打賞,謝謝.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM