熱更新
在介紹tolua前衅胀,我們首先來了解一下在游戲開發(fā)中骄恶,熱更新的概念琉苇。
熱更新是一種手游及App常用的更新方式,舉例來說娇钱,游戲上線后伤柄,玩家需要通過應用商店及其他渠道下載第一個版本。在運營的過程中文搂,如游戲需要更換UI适刀、修改邏輯、開放功能等煤蹭,此時若不使用熱更新技術(shù)笔喉,就需要重新打包,那么玩家也就需要通過應用商店或其他渠道重新下載游戲硝皂。 熱更新可以在不重新下載客戶端的情況下常挚,更新游戲的內(nèi)容。
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">目前手游這部分做得普遍比較成熟吧彪,大大小小的內(nèi)容升級基本都通過熱更新來完成</figcaption>
然而c#是一門編譯型語言待侵,其運行之前需要進行編譯丢早,而編譯的過程在移動平臺無法完成姨裸,所以當我們游戲的邏輯更改,代碼發(fā)生變化時怨酝,我們就需要重新在開發(fā)環(huán)境下編譯傀缩,然后重新打包,讓玩家下載最新版本农猬。這個過程中赡艰,會下載很多不需要更新的資源,便會增加玩家的時間及流量消耗斤葱,造成不好的用戶體驗慷垮。因此在移動平臺中便就出現(xiàn)了熱更新技術(shù)揖闸。
- 在unity中,主要的熱更新方式有如下三種:
1.使用Lua編寫游戲邏輯料身;
Lua是一個小巧的腳本語言汤纸,由標準C編寫而成,幾乎在所有操作系統(tǒng)和平臺上都可以編譯芹血,運行贮泞。
使用lua熱更新就是在Unity環(huán)境里內(nèi)嵌一個lua虛擬機,經(jīng)常變動的和對執(zhí)行效率沒要求的邏輯用Lua實現(xiàn)幔烛,游戲啟動時加載服務器上最新的lua字節(jié)碼來執(zhí)行游戲啃擦。lua代碼都是運行時才編譯的,不運行的時候就如同一張圖片饿悬、一段音頻一樣令蛉,都是文件資源;所以更新邏輯只需要更新腳本狡恬,不需要再編譯言询,因而lua能輕松實現(xiàn)“熱更新”。
其實諸如python傲宜,javascript等腳本語言的話运杭,都是可以實現(xiàn)這個功能的。只不是目前幾個開源的函卒、成熟的熱更新方案都是基于lua的辆憔。
2.C#Light
C#Light是一個簡單的嵌入式腳本,模仿c#的語法風格报嵌,完全由pure c#寫成
3.C#反射技術(shù)
可以將部分邏輯提取至一個單獨的代碼庫工程中虱咧,打包為DLL,將DLL打包為AssetBundle锚国,Unity程序動態(tài)加載AssetBundle中的DLL文件腕巡,使用反射機制來調(diào)用代碼。用C#反射加載程序集的方式可以動態(tài)的從assetBundle資源包或其他資源包里加載腳本到工程中血筑。但因為蘋果官方禁止iOS下的程序熱更新绘沉,JIT在iOS下無效,所以這種方式無法在ios使用
本文中主要來了解第一種方式豺总,在unity的lua熱更新中车伞,有ulua、slua喻喳、xlua另玖、tolua等多種熱更新方案,這些方案提供了C#與Lua的互相調(diào)用機制。在本文我們以現(xiàn)今市面最常見的tolua為例谦去,通過一個小項目給讀者介紹tolua在unity中的使用方法慷丽。
注:本文中僅介紹tolua的用法,不會詳細介紹tolua熱更新的方法鳄哭,如需要了解tolua熱更新可以通過toluaLuaFramework框架作者的博客及LuaFramework基礎來了解盈魁、學習。
ToLua使用
Tolua是Unity靜態(tài)綁定lua的一個解決方案窃诉,它通過C#中集成lua的插件杨耙,可以自動生成用于在lua中訪問Unity的綁定代碼,并把C#中的常量飘痛、變量珊膜、函數(shù)、屬性宣脉、類以及枚舉暴露給lua车柠。其從cstolua衍變而來。
既然要了解Tolua塑猖,第一步肯定是先從Tolua作者的GitHub下載Tolua資源GitHub - topameng/tolua: The fastest unity lua binding solution 同時我們可以通過其GitHub來了解Tolua的主要特性竹祷,也可以加tolua技術(shù)交流群進行討論及學習(在GitHub中有群號)。
下載完成后可以看到tolua文件夾中的目錄結(jié)構(gòu)羊苟,如下圖:
我們只需要將「Assets」塑陵、「Unity5.x」、「Luajit64」蜡励、「Luajit」四個文件夾復制到我們的工程文件夾中令花。 加載完成后,Unity中會出現(xiàn)如下提示框凉倚,我們點擊確定
然后在unity中就可以看到Tolua的主要文件列表
ToLua案例
在了解了基本的熱更新概念兼都,及ToLua資源的加載后,我們通過一個小的案例稽寒,來初步的掌握ToLua在Unity中的使用方法扮碧。 在本文中,我們使用ToLua來制作一個可以用按鍵控制滾動的小球杏糙,如下圖所示:
學習或使用過Unity的讀者應該能夠非常輕松的使用C#寫出這個小游戲慎王,那么我們現(xiàn)在來看使用ToLua是如何達到上圖效果的。
我們直接來看代碼搔啊,下面會對代碼進行逐行解釋:
Control.lua
Control = {}
local this = Control
require('Music')
local GameObject = UnityEngine.GameObject
local Input = UnityEngine.Input
local AudioSource = UnityEngine.AudioSource
local Rigidbody = UnityEngine.Rigidbody
local Color = UnityEngine.Color
local Sphere
local rigi
local force
function this.Start()
Sphere = GameObject.Find('Sphere')
Sphere : GetComponent('Renderer').material.color = Color(1, 0.1, 1)
Sphere : AddComponent(typeof(AudioSource))
coroutine.start(Music.PlaySound)
Sphere : AddComponent(typeof(Rigidbody))
rigi = Sphere : GetComponent('Rigidbody')
force = 5
end
function this.Update()
local h = Input.GetAxis('Horizontal')
local v = Input.GetAxis('Vertical')
rigi : AddForce(Vector3(h, 0, v) * force)
end
Music.lua
--協(xié)程下載
--這里使用Tolua中提供的coroutine.www
Music = {}
local this = Music
function this.PlaySound()
local audio = UnityEngine.GameObject.Find('Sphere') : GetComponent('AudioSource')
local url = UnityEngine.WWW('https://etnly.oss-cn-shanghai.aliyuncs.com/%E5%B2%A1%E9%83%A8%E5%95%93%E4%B8%80%20-%20%E9%81%BA%E3%82%B5%E3%83%AC%E3%82%BF%E5%A0%B4%E6%89%80%EF%BC%8F%E6%96%9C%E5%85%89.ogg')
coroutine.www(url)
audio.clip = url : GetAudioClip()
audio : Play()
end
首先柬祠,我們在project面板中創(chuàng)建Script文件夾,下一層創(chuàng)建Lua文件夾负芋,這個文件夾會存放我們所有的lua腳本。
然后我們來詳細解釋上方的代碼:
Control = {} : 在lua中沒有類的概念,第一行中我們用lua表模擬一個類旧蛾,類名為Control莽龟;
local this = Control : 既然在lua中不存在類的概念,那也不會存在this的用法锨天,這里同樣的毯盈,我們模擬一個this,讓this = Control類病袄;
require('Music’) : lua通過require函數(shù)來加載模塊(希望讀者可以自行了解lua中模塊的含義)在本行中Muisc模塊是一個下載并播放音樂的協(xié)程模塊搂赋,具體代碼在Muisc.lua中;
local GameObject = UnityEngine.GameObject : 這里及其以下四行都是對Unity中的類益缠、方法進行加載或者說調(diào)用脑奠,我們可以直接在代碼中使用UnityEngine.GameObject,或把UnityEngine.GameObject賦給一個變量(如第一行中幅慌,lua使用表來模擬類宋欺,那這里的GameObject也就是一個table類型);
local Sphere : 這里及以下兩行胰伍,我們定義了幾個變量齿诞;
function this.Start() end :這是lua中的函數(shù),this的含義在之前有提到骂租,我們也可以寫成Control.Start()祷杈, 我們在start函數(shù)中進行一些必要的初始化操作,可以把它看成Unity中的start(我們也可以給它起別的名字渗饮,這個函數(shù)的名字和之后我們在Unity中的調(diào)用沒有必然聯(lián)系)吠式,不要忘了加后面的end,這句話代表此方法的結(jié)尾抽米;
Sphere = GameObject.Find('Sphere') : 我們通過GameObject.Find來找到Unity中的小球(需要注意特占,lua腳本無法綁定在Unity中的物體上,所以也無法直接在Unity的面板中綁定Unity中的對象云茸,我們只有通過查找的方式來找到Unity中的物體)是目;
Sphere : GetComponent('Renderer').material.color = Color(1, 0.1, 1) :這一行中,我們使用GetComponent通過獲取Renderer組件标捺,改變小球的顏色 懊纳;
Sphere : AddComponent(typeof(AudioSource)) : 使用AddComponent,給小球添加AudioSource組件亡容;
coroutine.start(Music.PlaySound) : 開啟協(xié)程嗤疯, 我們可以直接看到 Music.lua這個腳本,在腳本中闺兢,我們使用ToLua封裝的coroutine.www()方法茂缚,來下載音樂,并通過之后的代碼來播放音樂;
Sphere : AddComponent(typeof(Rigidbody)) : 給小球添加剛體 脚囊;
rigi = Sphere : GetComponent('Rigidbody') : 獲取小球的剛體龟糕,將其賦給rigi ;
force = 5 : 這里作為力的大谢谠拧讲岁;
function this.Update() end : 與之前start函數(shù)類似,我們可以將其看作是Unity中的Update(再次聲明衬以,此處Lua函數(shù)名和Unity中的調(diào)用沒有必然聯(lián)系)缓艳;
local h = Input.GetAxis('Horizontal') : 這一行及下一行,就是獲取按下相應按鍵看峻,相應軸上的位移量 阶淘;
rigi : AddForce(Vector3(h, 0, v) * force) : 通過剛體的AddForce方法,給小球施加力备籽;
這就是我們整個例子的Tolua腳本使用說明舶治,那么我們該如何在Unity中來調(diào)用這些腳本呢。 下面我們來了解在C#中調(diào)用ToLua的方法车猬,代碼如下所示:
using UnityEngine;
using LuaInterface;
public class Control : MonoBehaviour {
LuaState lua = null;
LuaFunction luaFunc = null;
void Start () {
new LuaResLoader();
lua = new LuaState();
lua.Start();
LuaBinder.Bind(lua);
string luaPath = Application.dataPath + "/Scripts/Lua";//注意這里的文件位置
lua.AddSearchPath(luaPath);
lua.DoFile("Control.lua");
CallFunc("Control.Start", gameObject);//調(diào)用lua中的this.Start函數(shù)
}
void Update () {
CallFunc("Control.Update", gameObject);////調(diào)用lua中的this.Update函數(shù)
}
private void OnApplicationQuit()
{
lua.Dispose();
lua = null;
}
void CallFunc(string func, GameObject obj){
luaFunc = lua.GetFunction(func);
luaFunc.Call(obj);
luaFunc.Dispose();
luaFunc = null;
}
}
我們可以通過這段代碼來了解一些C#中調(diào)用Tolua的基本操作:
1.new LuaState() : 初始化Lua虛擬機
2.LuaState.Start() :開啟Lua虛擬機
3.LuaState.AddSearchPath(fullPath):添加目錄地址
4.LuaBinder.Bin(LuaState):向Lua虛擬機注冊Wrap類
5.new LuaResLoader() :自定義加載器加載lua文件
6.LuaState.DoFile()霉猛、LuaState.Require():加載Lua文件/模塊
7.LuaState.GetFunction:獲取Lua方法
8.LuaState.GetFunction.Call():調(diào)用Lua函數(shù)
9.Luafunction.Dispose(),LuaState.Dispose():釋放內(nèi)存
轉(zhuǎn)載于:https://zhuanlan.zhihu.com/p/42472089