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<Component>("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<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);
}
</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<JsValue, JsValue[], JsValue> func);
public ClrFunctionInstance(Engine engine, Func<JsValue, JsValue[], JsValue> 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]