1. 程式人生 > >ToLua熱更新之LuaFramework框架之編寫Lua邏輯(3)

ToLua熱更新之LuaFramework框架之編寫Lua邏輯(3)

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

運行遊戲,即可用鍵盤的控制坦克移動。

圖:用鍵盤的控制坦克移動

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))”。

圖:修改CustomSetting

3)生成wrap檔案

點選選單欄的Lua→Clear wrap files和Lua→Generate All,重新生成wrap檔案。由於剛剛在customTypeList添加了類,所以會生成TestLuaFun類的wrap檔案TestLuaFunWrap.cs。

圖:生成wrap檔案

開啟TestLuaFunWrap.cs,可以看到TestLuaFun註冊了Log方法。關於static int Log(IntPtr L)的具體含義,請參見《programing in lua》中lua與c++互動的章節。

圖:TestLuaFunWrap

4)測試API

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

--主入口函式。從這裡開始lua邏輯
function Main()					
	TestLuaFun.Log()  
end

圖:呼叫自定義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);
	}
}
 

圖:建立lua虛擬機器,執行lua程式碼

實際上LuaFramework也是用了相似的方法,框架啟動後,會建立LuaManager、LuaLooper的例項。LuaManager建立lua虛擬機器並呼叫Main.lua的Main方法,LuaLooper處理了UpdateBeat相關的事情。如下所示:

圖:LuaManager的啟動過程