Skip to main content
 首页 » 资源教程 » Unity3D教程

Unity3D热更新LuaFramework入门实战(3)——编写Lua逻辑

2016年10月15日 16:33:3413530

为实现代码热更新,在Unity3D中使用lua,然而为此也需付出不少代价。其一,使代码结构混乱(尽管可以优化),其二降低了运行速度,其三增加学习成本(还要多学一门语言)。为了热更新,所有的逻辑都要用lua编写,那么怎样用lua编写游戏逻辑呢?

1、Lua的Update方法

第一篇“代码热更新”演示了用lua打印HelloWorld的方法,第二篇“资源热更新”演示了加载坦克模型的方法。这一篇要把两者结合起来,用lua实现“用键盘控制坦克移动”的功能。用Lua和用c#编写的Unity3D程序大同小异,只需正确使用API即可,Lua语言的知识请参见《programing in lua》这本书。


1)Update方法

出于效率的考虑,tolua提供了名为UpdateBeat的对象,在LuaFramework中,只需给UpdateBeat添加回调函数,该函数便会每帧执行,相当于Monobehaviour的Update方法。Lua代码如下所示:

function Main()					
    UpdateBeat:Add(Update, self)
end
 
function Update()
	LuaFramework.Util.Log("每帧执行一次");
end

除了UpdateBeat,tolua还提供了LateUpdateBeat和FixedUpdateBeat,对应于Monobehaviour中的LateUpdate和FixedUpdate。


2)控制坦克

现在编写“用键盘控制坦克移动”的lua代码,加载坦克模型后,使用UpdateBeat注册每帧执行的Update方法,然后在Update方法中调用UnityEngine.Input等API实现功能。代码如下:


local go; --加载的坦克模型
 
--主入口函数。从这里开始lua逻辑
function Main()
					
	LuaHelper = LuaFramework.LuaHelper;
	resMgr = LuaHelper.GetResManager();
	resMgr:LoadPrefab('tank', { 'TankPrefab' }, OnLoadFinish);
end
 
--加载完成后的回调--
function OnLoadFinish(objs)
	go = UnityEngine.GameObject.Instantiate(objs[0]);
	LuaFramework.Util.Log("LoadFinish");
	
	UpdateBeat:Add(Update, self)
end
 
--每帧执行
function Update()
	LuaFramework.Util.Log("每帧执行");
	
	local Input = UnityEngine.Input;
	local horizontal = Input.GetAxis("Horizontal");
	local verticla = Input.GetAxis("Vertical");
	
	local x = go.transform.position.x + horizontal
	local z = go.transform.position.z + verticla
	go.transform.position = Vector3.New(x,0,z)
end

运行游戏,即可用键盘的控制坦克移动。


Unity3D热更新LuaFramework入门实战(3)——编写Lua逻辑 Unity3D教程 第1张

图:用键盘的控制坦克移动

2、自定义API

框架中提供了数十个可供lua调用的c#类,但这些往往不够用,需要自己添加,本节将介绍添加自定义API的方法。


1)编写c#类

例如,编写TestLuaFun.类,它包含一个静态方法Log,会打印出“《Unity3D网络游戏实战》是一本好书!”和“《手把手教你用c#制作rpg游戏》也是一本好书!”两行文本。

using UnityEngine;
using System.Collections;
 
public class TestLuaFun 
{
	public static void Log() 
	{
		Debug.Log("《Unity3D网络游戏实战》是一本好书!");
		Debug.Log("《手把手教你用c#制作rpg游戏》也是一本好书!");
	}
}

2)修改CustomSetting

打开CustomSetting.cs,在customTypeList中添加一句“_GT(typeof(TestLuaFun))”。

Unity3D热更新LuaFramework入门实战(3)——编写Lua逻辑 Unity3D教程 第2张

图:修改CustomSetting


3)生成wrap文件

点击菜单栏的Lua→Clear wrap files和Lua→Generate All,重新生成wrap文件。由于刚刚在customTypeList添加了类,所以会生成TestLuaFun类的wrap文件TestLuaFunWrap.cs。

Unity3D热更新LuaFramework入门实战(3)——编写Lua逻辑 Unity3D教程 第3张

图:生成wrap文件


打开TestLuaFunWrap.cs,可以看到TestLuaFun注册了Log方法。关于static int Log(IntPtr L)的具体含义,请参见《programing in lua》中lua与c++交互的章节。

Unity3D热更新LuaFramework入门实战(3)——编写Lua逻辑 Unity3D教程 第4张

图:TestLuaFunWrap


4)测试API

修改main.lua,调用TestLuaFun.Log() ,即可看到效果。

--主入口函数。从这里开始lua逻辑
function Main()					
	TestLuaFun.Log()  
end

Unity3D热更新LuaFramework入门实战(3)——编写Lua逻辑 Unity3D教程 第5张

图:调用自定义API


3、原理

tolua实现了LuaInterface,抛开luaFramework,只需创建lua虚拟机,便能在c#中调用lua代码,如下所示。

using UnityEngine;
using System.Collections;
using LuaInterface;
 
public class test : MonoBehaviour
{
	void Start () 
	{
		//初始化
		LuaState lua = new LuaState();
		LuaBinder.Bind(lua);
		//lua代码
		string luaStr =
			@"                
                print('hello tolua#, 广告招租')
				LuaFramework.Util.Log('HelloWorld');
				TestLuaFun.Log()                
            ";
		//执行lua脚本
		lua.DoString(luaStr);
	}
}

Unity3D热更新LuaFramework入门实战(3)——编写Lua逻辑 Unity3D教程 第6张

图:创建lua虚拟机,执行lua代码

实际上LuaFramework也是用了相似的方法,框架启动后,会创建LuaManager、LuaLooper的实例。LuaManager创建lua虚拟机并调用Main.lua的Main方法,LuaLooper处理了UpdateBeat相关的事情。如下所示:

Unity3D热更新LuaFramework入门实战(3)——编写Lua逻辑 Unity3D教程 第7张

图:LuaManager的启动过程


笔者也是刚刚接触LuaFramework不久,文章错误之处在所难免,请大家多加包涵。最后是广告时间:

《仙剑5前传之心愿》是笔者两年前发起的一款仙剑同人游戏,使用Unity3D制作,是市面上第一款能够完成的3D仙剑同人游戏。如今我们各自踏上游戏开发一途,似乎要做点什么以致敬国产经典之作,在追求商业成就的同时,勿忘初心。可以在pal5h.com下载该游戏。

Unity3D热更新LuaFramework入门实战(3)——编写Lua逻辑 Unity3D教程 第8张

图:《仙剑5前传之心愿》截图

更多AR教程就在中国AR网(http://www.chinaar.com/)


中国AR网(微信公众号:armeiti)


评论列表暂无评论
发表评论