Unity XLua熱更新
持續更新
相關連結
基礎案例
0基礎的先看 xlua遷入專案
/*
* Author : Jk_Chen
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
/// <summary>
/// 熱更新類,進行程式碼的修復
/// </summary>
public class XLuaFix : MonoBehaviour
{
static LuaEnv lua;
static int tmp = 2;
void Awake()
{
lua = new LuaEnv();
// 簡單執行Lua語句
lua.DoString("print 'lua print'");
// 呼叫C#類的公有靜態方法
lua.DoString("CS.UnityEngine.Debug.Log('cs debug')");
lua.DoString("CS.XLuaFix.Print()");
// 先讓某個類的私有成員可訪問,再呼叫私有靜態方法
lua.DoString("xlua.private_accessible(CS.XLuaFix)");
lua.DoString("CS.XLuaFix.PrivatePrint()");
// 修改靜態變數
lua.DoString("CS.XLuaFix.tmp=3");
lua.DoString("print('修改後的靜態變數為:' .. CS.XLuaFix.tmp)");
}
public static void Print()
{
Debug.Log("public static");
}
private static void PrivatePrint()
{
Debug.Log("private static");
}
private void OnDestroy()
{
lua.Dispose();
}
}
關於XLua的生成程式碼和程式碼注入
程式碼需要進行熱更新的時候,需要進行生成程式碼和程式碼注入。
請在每次修改程式碼後(執行前)都執行一遍該操作。
程式碼注入後Debug會比較麻煩,因為Log內尋找不到是哪行程式碼的執行結果。
看得到,但是不能通過點選直接找到哪行
原來是這樣的
如果不需要熱更新可以把生成的程式碼Clear掉
簡單熱更新
必要步驟
- 需要熱更新的類前加[Hotfix]
- 執行前生成程式碼和程式碼注入
/*
* Author : Jk_Chen
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
/// <summary>
/// 熱更新類,進行程式碼的修復
/// </summary>
[Hotfix]
public class XLuaFix : MonoBehaviour
{
static LuaEnv lua;
public static int tmp = 2;
void Awake()
{
lua = new LuaEnv();
// 呼叫帶參函式
lua.DoString("CS.XLuaFix.Print(CS.XLuaFix.tmp)");
// 修改函式
lua.DoString(
@"xlua.hotfix(CS.XLuaFix,'Print',function(value)
CS.UnityEngine.Debug.Log('After ' .. value*value)
end)"
);
// 呼叫修改後的函式
lua.DoString("CS.XLuaFix.Print(CS.XLuaFix.tmp)");
}
public static void Print(int value)
{
Debug.Log("Defore " + value);
}
private void OnDestroy()
{
lua.Dispose();
}
}
程式碼修復成功,但是報錯了。這個錯誤官方有回答:
這是由於C#還存在指向lua虛擬機器裡頭某個函式的delegate,為了防止業務在虛擬機器釋放後呼叫這些無效(因為其引用的lua函式所在虛擬機器都釋放了)delegate導致的異常甚至崩潰,做了這個檢查。
怎麼解決?釋放這些delegate即可,所謂釋放,在C#中,就是沒有引用:
你是在C#通過LuaTable.Get獲取並儲存到物件成員,賦值該成員為null;
你是在lua那把lua函式註冊到一些事件事件回撥,反註冊這些回撥;
如果你是通過xlua.hotfix(class, method, func)注入到C#,則通過xlua.hotfix(class, method, nil)刪除;
要注意以上操作在Dispose之前完成。
所以我們在釋放虛擬機器之前釋放這些委託即可:
private void OnDestroy()
{
// 釋放委託
lua.DoString(
@"xlua.hotfix(CS.XLuaFix,'Print',nil)"
);
lua.Dispose();
}
使用Lua指令碼檔案
之前使用到的都是在C#程式碼內使用DoString來呼叫Lua,這樣有一個很麻煩的地方就是,由於每次都會修改程式碼,所以都需要生成和注入。而且和我們的熱更新也不搭嘎。
所以我們現在使用指令碼檔案的方式。require函式可以載入一個lua指令碼,但如果lua指令碼不在Resources路徑下,或者不在預設的目錄下,此時是載入不到對應的lua指令碼的。
我們需要自己寫一個loader來適配lua指令碼的位置:
c#程式碼:
/*
* Author : Jk_Chen
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
/// <summary>
/// 熱更新類,進行程式碼的修復
/// </summary>
[Hotfix]
public class XLuaFix : MonoBehaviour
{
static LuaEnv lua;
public static int tmp = 2;
void Awake()
{
lua = new LuaEnv();
// 定義loader,從Assets/Lua目錄下讀取,已自帶.lua.txt
// 例如讀取Assets/Lua/xx.lua.txt只需要 lua.DoString("require('xx')");
lua.AddLoader((ref string file) => {
string path = System.IO.Path.Combine("Assets/Lua", file + ".lua.txt");
if (System.IO.File.Exists(path))
{
return System.IO.File.ReadAllBytes(path);
}
else
{
return null;
}
});
lua.DoString("require('XLuaFix')");
}
public static void Print(int value)
{
Debug.Log("Defore " + value);
}
private void OnDestroy()
{
// 釋放委託
lua.DoString("require('XLuaFixDispose')");
// 釋放虛擬機器
lua.Dispose();
}
}
lua指令碼: XLuaFix.lua.txt
-- 呼叫帶參函式
CS.XLuaFix.Print(CS.XLuaFix.tmp)
-- 修改函式
xlua.hotfix(CS.XLuaFix,'Print',function(value)
CS.UnityEngine.Debug.Log('After ' .. value*value)
end)
-- 呼叫修改後的函式
CS.XLuaFix.Print(CS.XLuaFix.tmp)
lua指令碼: XLuaFixDispose.lua.txt
-- 釋放委託
xlua.hotfix(CS.XLuaFix,'Print',nil)
本人是用notepad寫lua指令碼的
notepad配置部落格
相關文章
- xLua熱更新外掛
- 熱更新解決方案--xlua學習筆記筆記
- Unity匯入xLua流程Unity
- 【Unity】XLua巨坑彙總Unity
- Unity3D熱更新全書-何謂熱更新,為何熱更新,如何熱更新Unity3D
- xLua熱更開發之一:初見xlua,你好
- 深入理解xLua基於IL程式碼注入的熱更新原理
- Unity3D熱更新全書-PageZeroUnity3D
- Unity3D熱更新全書FAQUnity3D
- Unity3D熱更新之LuaFramework篇[08]--熱更新原理及熱更伺服器搭建Unity3DFramework伺服器
- Unity3D熱更新之LuaFramework篇[09]--資源熱更新與程式碼熱更新的具體實現Unity3DFramework
- Unity 小遊戲轉換(一)—— WebGL+XLua匯出Unity遊戲Web
- Unity3D熱更新全書-重頭再來Unity3D
- Unity3D熱更新全書-指令碼(五) NGUIUnity3D指令碼NGUI
- Unity 開源雙端框架 ET 中初嘗熱更新技術Unity框架
- Unity3D熱更新全書-指令碼(二) 兩級分化Unity3D指令碼
- Unity3D熱更新之LuaFramework篇[07]--怎麼讓unity物件繫結Lua指令碼Unity3DFramework物件指令碼
- Unity3D熱更新全書-指令碼(一) 初識指令碼Unity3D指令碼
- C#Light Unity邏輯熱更新解決方案0.20 釋出C#Unity
- C#Lite Unity熱更新開源解決方案改名C#LightC#Unity
- Unity3d熱更新全書-載入(一)從AssetBundle說起Unity3D
- Unity3D熱更新全書-下載 唯一的一篇Unity3D
- Unity 熱更新例項一、C#Light 和UI系統使用例項UnityC#UI
- xlua - 增加protobuf庫
- Vuex之熱更新Vue
- Web前端熱更新Web前端
- webpack 熱更新原理Web
- Unity3D熱更新全書-指令碼(三) C#LightEvil語法與除錯Unity3D指令碼C#除錯
- uni-app熱更新APP
- Flutter 應用熱更新Flutter
- 熱更新配置檔案
- React Native 熱更新React Native
- Webpack 熱更新機制Web
- 遊戲熱更新雜談遊戲
- Hyperf - 熱更新Watcher
- 更新了有趣細節的 Unity 8Unity
- [Unity3D]Unity3D遊戲開發之Lua與遊戲的不解之緣終結篇:UniLua熱更新全然解讀Unity3D遊戲開發
- C#版的eval,C#Light開源嵌入式指令碼,unity熱更新不再愁C#指令碼Unity