zoukankan      html  css  js  c++  java
  • 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还是有点远的.由于时间比较零碎,因此其余的部分会在有空的时候继续提供.如果文章中有任何错误或者疑问欢迎提出,如果文章对你有帮助也欢迎打赏,谢谢.

  • 相关阅读:
    python-学习笔记之-Day5 双层装饰器 字符串格式化 python模块 递归 生成器 迭代器 序列化
    python学习笔记-day4笔记 常用内置函数与装饰器
    Python学习笔记-Day3-python内置函数
    Python学习笔记-Day3-文件操作
    Python学习笔记-Day3-python函数
    Python学习笔记-Day3-python关键字
    Python学习笔记-Day3-set集合操作
    Python学习笔记-Day2-Python基础之列表操作
    Python学习笔记-Day2-Python基础之元组操作
    Python学习笔记-Day2-Python基础之字典操作
  • 原文地址:https://www.cnblogs.com/ahl5esoft/p/14166893.html
Copyright © 2011-2022 走看看