最近项目准备用uLua实现部分代码热更新。于是去了解了一下uLua的使用方法。既然是项目后期想用uLua,自然有不少代码需要改造,我看了一下最简单的就是先从MonoBehavior开始改造。项目中有不少直接挂在GameObject上的,其中的逻辑相对比较独立,就先从这个开始试一下。
实验用的脚本长这样:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MonoBeh : MonoBehaviour {
// Use this for initialization
public List<Transform> gameObjects;
public float rotateSpeed = 90.0f;
void Start () {
}
// Update is called once per frame
void Update () {
for (int idx = 0; idx < gameObjects.Count; ++idx)
{
gameObjects[idx].Rotate(0, Time.deltaTime * rotateSpeed, 0);
}
}
}
代码很简单,就是让列表里面的物体一直转转转~
要使用uLua,首先要从uLua官网下载uLua的Unity插件,目前的版本是1.2.1,需要注意的是uLua在旧版本的Unity运行会有问题,会把Unity直接整崩掉,所以最好升级到4.6.2以上的Unity再用。
使用uLua的目的是把容易变动的逻辑部分作为Lua脚本嵌入项目,以后这些脚本就可以像普通资源一样通过AssetBundle实现热更新了。要使用Lua脚本,需要用LuaScriptMgr对象,调用DoString方法就可以执行Lua脚本了。下面是改造后的MonoBehavior代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using LuaInterface;
public class MonoBeh2 : MonoBehaviour {
public TextAsset luaScript;
public List<Transform> gameObjects;
public float rotateSpeed = 90.0f;
private LuaScriptMgr mgr;
private LuaFunction funUpdate;
private LuaFunction funSetGameObjects;
private LuaFunction funSetSpeed;
// Use this for initialization
void Start () {
mgr = new LuaScriptMgr();
mgr.Start();
if (luaScript != null)
{
mgr.DoString(luaScript.text);
funUpdate = mgr.GetLuaFunction("logic.Update");
funSetGameObjects = mgr.GetLuaFunction("logic.SetGameObjects");
funSetSpeed = mgr.GetLuaFunction("logic.SetRotateSpeed");
if (funSetGameObjects != null)
{
funSetGameObjects.Call((object)gameObjects.ToArray());
}
if (funSetSpeed != null)
{
funSetSpeed.Call((double)rotateSpeed);
}
}
}
// Update is called once per frame
void Update () {
if (funUpdate != null)
{
//fun.Call(这里参数不会写)
funUpdate.Call((double)Time.deltaTime);
}
}
void OnDestroy()
{
if (funUpdate != null)
{
funUpdate.Release();
}
if (funSetGameObjects != null)
{
funSetGameObjects.Release();
}
if (funSetSpeed != null)
{
funSetSpeed.Release();
}
}
}
这样我们就把Update中做核心工作的代码拿了出去,放到了luaScript中。Lua中的脚本是这样的:
logic = logic or {}
logic.gameObjects = gameObjects or {}
logic.rotateSpeed = 0
function logic.SetGameObjects(objects)
for i = 0, objects.Length - 1, 1 do
if logic.gameObjects[i] == nil then
logic.gameObjects[i] = objects[i]
end
end
print "Call Fun:SetGameObjects"
end
function logic.SetRotateSpeed(speed)
logic.rotateSpeed = speed
print "Call Fun:SetRotateSpeed "
end
function logic.Update(deltaTime)
for i, v in next, logic.gameObjects do
v:Rotate(0, logic.rotateSpeed * deltaTime, 0)
end
end
Unity中的类已经通过uLua生成的xxxWrap.cs的代码引入到Lua中了,所以我们可以直接用,但是我们自己的数据是需要自己传给Lua的,这里我用了两个Set方法。另外需要说的一点是Lua中不能直接用Time.deltaTime,这个值始终是0,所以我在Update里面手动传入了这个值,也可能是我用的方式不对吧,如果有知道怎么用的欢迎交流。总之,作为一次实验性的探索,代码还是写的比较丑的,毕竟只是想先学会用。