什麼是XLua
XLua是騰訊開源的一款Unity熱更新插件
XLua與其他熱更新方案比優勢
- GitHub上星數最多
- 可以更多地使用C#代碼
- Lua兼容多
- 掌握Lua在遊戲行業更有競爭優勢
XLua熱更新流程
- 把L和AB文件放在服務器上(這裏Lua腳本文件咱就叫L)
- Unity應用從服務器下載L,L寫入在本地,編譯本地L,L內容是修改C#腳本內容,編譯修改後的C#腳本,哇,熱更了腳本
- 再次熱更腳本,使C#腳本可以從服務器下載AB文件,把AB文件轉換成新遊戲對象(C#來寫Lua來調簡單些),有了對象,再次熱更腳本讓它在場景中顯示,哇,熱更了資源
教程環境
- Unity2018.4.14f1
- XLua最新版本
- Win10家庭版64位1909
安裝過程
- 打開自己某個Unity項目工程,該工程這裏咱取名叫B
- 打開從GitHub下載的XLua,在B與之相對應目錄下拷入Xlua相關文件(如下圖)
- Unity編輯打開PlayerSettings中的相關設置,其中鍵入”HOTFIX_ENABLE“(如下圖)
- 在B與之相對應目錄下,拷入3個Unity編輯器安裝目錄中的dll文件(如下圖)
- 之後可運行XLua自帶案例試試,每次修改腳本後都要先點1再點3,只有代碼衝突才點2(如下圖)
- 在服務器上放3個Lua文件,1是補丁腳本,2是釋放腳本,3是XLua中的庫(如下圖)
開始寫代碼
- 寫一個xlua熱更管理器腳本,把它掛載在某個遊戲對象上
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using XLua;
[Hotfix] //所有要熱更的類都要打上這個標籤
public class HotFixScript : MonoBehaviour
{
public static Dictionary<string, GameObject> prefabDict = new Dictionary<string, GameObject>(); //字典保存從AB文件加載的遊戲對象
private LuaEnv luaEnv;
private void Start()
{
luaEnv = new LuaEnv();
luaEnv.AddLoader(MyLoader); //加載器方便加載而生,可以加載到該路徑下的一些lua文件
luaEnv.DoString("require'fish2'"); //加載fish2
}
private byte[] MyLoader(ref string filepath)
{
var temp1 = Application.persistentDataPath; //本地可讀寫的目錄
var temp2 = ".lua.txt";
var temp3 = temp1 + "/" + filepath + temp2;
return Encoding.UTF8.GetBytes(File.ReadAllText(temp3));
}
private void OnDisable()
{
luaEnv.DoString("require'fishDispose2'"); //加載fishDispose2,裏面有釋放的lua代碼
}
private void OnDestroy()
{
luaEnv.Dispose(); //釋放環境
}
[LuaCallCSharp] //既然這個方法是要被Lua調用的,所以要加上這個標籤,性能更好,否則將會使用反射來搞性能更差
public void LoadResource(string resName, string filePath) //從遠程加載ab轉換對象放入緩存,這裏是提前用C#寫好方法,然後用Lua去調用
{
StartCoroutine(LoadResourceCorotine(resName, filePath));
}
private IEnumerator LoadResourceCorotine(string resName, string filePath)
{
var request = UnityWebRequestAssetBundle.GetAssetBundle(@"http://122.51.186.74/Book/AssetBundles/" + filePath);
yield return request.SendWebRequest();
var ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
var gameObject = ab.LoadAsset<GameObject>(resName);
prefabDict.Add(resName, gameObject);
}
[LuaCallCSharp]
public static GameObject GetGameObject(string goName) //獲取緩存的ab變成的對象
{
return prefabDict[goName];
}
}
- 上線版前放一個或多個腳本(如下),萬一上線版有新需求,就可以熱更新此腳本實現新類。
using UnityEngine;
using XLua;
[Hotfix]
public class HotClass2 : MonoBehaviour
{
[LuaCallCSharp]
public void Function1()
{
}
[LuaCallCSharp]
public void Function2()
{
}
}
- 打AB資源包(略)
- Lua釋放腳本(供參考)
xlua.hotfix(CS.Treasour,'CreatePrize',nil)--CS.Treasour表示類,'CreatePrize'表示類中方法,這裏要釋放掉
xlua.hotfix(CS.Bullect,'OnTriggerEnter',nil)
xlua.hotfix(CS.Bullect,'Start',nil)
xlua.hotfix(CS.CreateFish,'Update',nil)
xlua.hotfix(CS.CreateFish,'Start',nil)
- Lua補丁腳本(供參考)
local UnityEngine=CS.UnityEngine
local printTrue =true;
local util = require('util');
xlua.private_accessible(CS.Bullect)--開啓可以訪問私有成員
util.hotfix_ex(CS.Bullect,'OnTriggerEnter',function(self,other)--熱更方法,這個可以複寫原來方法,性能較差
self.OnTriggerEnter(self,other)--原來的方法
if printTrue then
local go =UnityEngine.GameObject.Find("Ainiyou").GetComponent("Text");--沒有泛型用這種形式
go.text = "ainiyou";
end
end)
xlua.hotfix(CS.Bullect,'Start',function(self)--熱更方法,這個是完全改寫
local b = self:GetComponent('BoxCollider');
print(b.isTrigger);
local brandom =UnityEngine.Mathf.FloorToInt(UnityEngine.Random.Range(0,8));--Lua沒有int的解決方案
print(brandom);
end)
util.hotfix_ex(CS.Treasour,'CreatePrize',function(self)
self: CreatePrize();
for i=0,4,1 do
local go=UnityEngine.GameObject.Instantiate(self.gold,self.transform.position+UnityEngine.Vector3(-10+i*10,0,0),self.transform.rotation)--Vector3在Lua沒有New
go.transform.SetParent(go.transform,self.cavas)
local go1=UnityEngine.GameObject.Instantiate(self.diamands,self.transform.position+UnityEngine.Vector3(0,10,0)+UnityEngine.Vector3(-10+i*10,0,0),self.transform.rotation)
go1.transform.SetParent(go1.transform,self.cavas)
end
end)
xlua.private_accessible(CS.CreateFish)
xlua.hotfix(CS.CreateFish,'Start',function(self)
self.hotFixScript:LoadResource('level3fish3','level3fish3.ab')--修改讓腳本可以加載ab
--self.hotFixScript:LoadResource('SeaWave','gameobject\\wave.ab')
end)
補充說明
- 個人一些配置,實現了給所有類打
[HotFix]
(如下圖)
- 打安裝包要把XLua案例刪掉
- 詳細教程請看官方文檔,水平有限,多多指教