雾岛之樱 發表於 2020-12-21 10:59:00

unity3d支持typescript开发

<h1 id="目录">目录</h1>
<ol>
<li>unity3d支持typescript开发(一)</li>
<li>unity3d支持typescript开发(二)</li>
<li>unity3d支持typescript开发(三)</li>
<li>unity3d支持typescript开发(四)</li>
<li>unity3d支持typescript开发(五)</li>
<li>unity3d支持typescript开发(六)</li>
</ol>
<h1 id="前言">前言</h1>
<p>由于之前的工作是在游戏公司做unity框架,该框架使用的是lua+unity的方案,而最近频繁接触typescript后,就有了想要在unity框架内支持typescript的想法.</p>
<p>早期的unity是支持javascript<code>后面简写为js</code>的,但是后来被unity抛弃了,其实让unity支持typescript<code>后面简写为ts</code>跟支持lua是很相似的,只需要找到一个可以在.net环境下执行js的解释器即可,而js可以通过编译ts来获得,那么即可支持ts了.</p>
<p>那么此次我们来完成一个示例,首先unity启动自会后会加载一个prefab,然后加载对应路径的js代码并调用onStart方法,该js方法内会调用console.log,而该函数会转而调用unity内的Debug.Log方法.</p>
<h1 id="net库">.net库</h1>
<p>https://github.com/sebastienros/jint 是比较符合当前条件的.net库, 但是该库只提供了基础的js环境, 而该环境中并不包含console对象.</p>
<h1 id="初始化jint">初始化jint</h1>
<p>首先在canvas下添加一个脚本,在该脚本内初始化jint,当Awake方法被触发的时候,加载prefab, C#代码如下:</p>
<pre><code>class DemoCanvas : MonoBehaviour
{
    private readonly Engine m_Engine = new Engine();

    private void Awake()
    {
      var prefab = Resources.Load&lt;Component&gt;("demo/Index");
      Instantiate(prefab, this.transform);
    }
}
</code></pre>
<h1 id="执行js脚本">执行js脚本</h1>
<p>由于上文中我们将Jint的初始化代码放在了Canvas内,因此js脚本的加载执行就不能参考canvas的流程来了,因为Instantiate的时候Awake会被触发如果这时候要调用Jint.Engine的话则需要将该字段开放,这样循环引用并不好,因此此处改为在prefab内开放一个方法用于初始化, C#代码如下:</p>
<pre><code>// js
console.log('hello world');

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

// DemoCanvas
public void Awake()
{
    var prefab = Resources.Load&lt;Component&gt;("demo/Index");
    Instantiate(prefab, this.transform).GetComponent&lt;DemoView&gt;().EvalScript(this.m_Engine);
}
</code></pre>
<p>运行以后出现了错误,这是由于Jint并没有提供console这个对象,因此需要自己扩展一个console对象.</p>
<h1 id="console对象">console对象</h1>
<p>阅读Jint的源码内我们可以发现,Jint的对象需要继承自ObjectInstance,然后调用FastAddProperty给该对象添加一个属性,该方法的定义如下:</p>
<pre><code>public void FastAddProperty(string name, JsValue value, bool writable, bool enumerable, bool configurable)
</code></pre>
<p>除了JsValue以外,其他的参数字面上跟js是一致的,这里就不解释了.由于console.log是一个函数,因此这里JsValue需要使用ClrFunctionInstance,ClrFunctionInstance的定义如下:</p>
<pre><code>public sealed class ClrFunctionInstance : FunctionInstance
{
    public ClrFunctionInstance(Engine engine, Func&lt;JsValue, JsValue[], JsValue&gt; func);
    public ClrFunctionInstance(Engine engine, Func&lt;JsValue, JsValue[], JsValue&gt; func, int length);

    public override JsValue Call(JsValue thisObject, JsValue[] arguments);
}
</code></pre>
<p>构造函数中有两个,其中一个包含了一个<code>int length</code>的参数,因为console.log是不限定参数个数的,因此我们使用另外一个不包含length的构造函数,C#代码如下:</p>
<pre><code>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.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);

    // 略
}
</code></pre>
<p>这里为了简化log方法内参数的判断,代码改为只对第一个值进行ToString的处理.</p>
<h1 id="结尾">结尾</h1>
<p>到了这里我们就已经完成了unity支持执行js脚本了,但是离支持ts还是有点远的.由于时间比较零碎,因此其余的部分会在有空的时候继续提供.如果文章中有任何错误或者疑问欢迎提出,如果文章对你有帮助也欢迎打赏,谢谢.</p><br><br>
来源:https://www.cnblogs.com/ahl5esoft/p/14166893.html
頁: [1]
查看完整版本: unity3d支持typescript开发