GameManager
1 2 3 4 5 6 7 8 9
| public void LaunchLua() { lua = LuaManager.Singleton.init(); System.GC.Collect(); System.GC.Collect(); }
|
LuaManager
先调用了构造函数。
LuaManager()
1 2 3 4 5 6 7
| private LuaManager() { luaMap = new Dictionary<string, byte[]>(); mLoadedLuaPBMap = new Dictionary<string, byte[]>(); LuaScrpitModel = System.Convert.ToBoolean(PlayerPrefs.GetInt(Application.dataPath + "LuaScrpiteModel", 0)); }
|
luaMap : 所有lua脚本 通过ab方式加载。
mLoadedLuaPBMap : 已加载的PB文件映射列表
luaScrpitModel : luaab模式运行
紧接着调用初始化函数。
init()
1 2 3 4 5 6 7 8 9
| public LuaEnv init() { if (luaEnv != null) { return luaEnv; }
luaEnv = new XLua.LuaEnv(); luaEnv.AddLoader(GetLuaBytes);
|
AddLoader : 增加一个自定义loader。
loader:一个包括了加载函数的委托,其类型为delegate byte[] CustomLoader(ref string filepath),当一个文件被require时,这个loader会被回调,其参数是调用require所使用的参数,如果该loader找到文件,可以将其读进内存,返回一个byte数组。如果需要支持调试的话,而filepath要设置成IDE能找到的路径(相对或者绝对都可以)。
GetLuaBytes()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public byte[] GetLuaBytes(ref string filePath) { string luaName = Path.GetFileNameWithoutExtension(filePath); if (luaScrpitModel) { if (luaMap.ContainsKey(luaName)) { return luaMap[luaName]; } else { Logger.err(string.Format("文件 : {0}未被加载,请检查AB!", filePath)); } } else { var files = Directory.GetFiles(UnityEngine.Application.dataPath + "/XLua/Lua/", luaName + ".lua", SearchOption.AllDirectories);
if (files.Length > 0) { return File.ReadAllBytes(files[0]); } else { Logger.err(string.Format("找不到文件 : {0},加载失败!", filePath)); } } return null; }
|
Path.GetFileNameWithoutExtension : 从路径字符串中得到文件名(不带扩展名)。
1 2 3 4
| LoadScripts();
string main = "main"; luaEnv.DoString(GetLuaBytes(ref main));
|
LoadScripts()
1 2 3 4 5 6 7 8 9 10 11 12 13
| public void LoadScripts() { if (!luaScrpitModel) { Debug.Log("加载lua 文件" + "=========文本==========="); return; } Debug.Log(System.DateTime.Now.ToString("hh:mm:ss:fff") + "加载lua 文件" + "=========AB=========="); luaMap.Clear(); LoadScripts("LuaAB"); LoadScripts("LuaBeanAB"); Debug.Log(System.DateTime.Now.ToString("hh:mm:ss:fff") + "加载lua 完成" + "=========AB=========="); }
|
如果是在AB运行模式下,会加载LuaAB与LuaBeanAB。
LoadScripts()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public void LoadScripts(string name) { string abname = StrFixed.Add_After_assetbundle(name); AssetBundle ab = AssetBundleRequestHelper.RequestAssetbundleBundleSync(name); if (ab == null) { Logger.err("没有lua文件" + name); return; } var scripts = ab.LoadAllAssets(); for (int i = 0, len = scripts.Length; i < len; ++i) { if (scripts[i] is TextAsset) { var lua = scripts[i] as TextAsset; string lname = lua.name.Replace(".lua", "").Replace(".Lua", ""); luaMap[lname] = lua.bytes; } } ab.Unload(true); }
|
StrFixed.Add_After_assetbundle : 加上资源的后缀 安卓aba ios为abi。
AssetBundleRequestHelper.RequestAssetbundleBundleSync : 从磁盘中同步加载AB对象。
遍历加载完毕后的LuaAB,将它们存储在luaMap后,将AB卸载。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| LoadScripts();
string main = "main"; luaEnv.DoString(GetLuaBytes(ref main)); startFunc = luaEnv.Global.Get<XLua.LuaFunction>("LuaStart"); updateFunc = luaEnv.Global.Get<Action<float>>("LuaUpdate"); fixedUpdateFunc = luaEnv.Global.Get<Action<float>>("FixedUpdate"); lateUpdateFunc = luaEnv.Global.Get<Action<float>>("LateUpdate"); stopFunc = luaEnv.Global.Get<XLua.LuaFunction>("LuaStop");
bool ios = false, android = false, editor = false; #if UNITY_EDITOR editor = true; #endif #if UNITY_ANDROID android = true; #endif #if UNITY_IPHONE ios = true; #endif bool dalu = false, taiwan = false, appstore = false, ttsdk = false, xianxing = false; #if DaLu dalu = true; #endif #if TaiWan taiwan = true; #endif #if AppStore appstore = true; #endif #if TTSDK ttsdk = true; #endif #if XianXing xianxing = true; #endif
luaEnv.Global.Get<Action>("InitGlobal")();
LuaActorManager = luaEnv.Global.Get<ILuaActorManager>("LuaActorManager").Singleton(); mLuaProtobufManager = luaEnv.Global.Get<ILuaProtobufManager>("LuaProtobufManager").Singleton(); mLuaServiceManager = luaEnv.Global.Get<ILuaServiceManager>("LuaServiceManager").Singleton(); LuaGameManager = luaEnv.Global.Get<ILuaGameManager>("LuaGameManager").Singleton();
luaRMessage = luaEnv.Global.Get<LuaRMessage>("LuaRMessage"); luaEventCallBack = luaEnv.Global.Get<LuaEventCallBack>("LuaEventCallback"); newFunc = luaEnv.Global.Get<LuaFunction>("New");
luaCollectPosition = luaEnv.Global.Get<Action>("LuaCollectPosition"); luaCollectIdle = luaEnv.Global.Get<Action<Actor>>("LuaCollectIdle"); luaCollectDash = luaEnv.Global.Get<Action<Actor, Skill>>("LuaCollectDash"); luaCollectMoveTo = luaEnv.Global.Get<Action<Actor, Vector3, Vector3>>("LuaCollectMoveTo"); luaCollectMove = luaEnv.Global.Get<Action<Actor, Vector3>>("LuaCollectMove"); luaCollectSummonAttack = luaEnv.Global.Get<Action<Actor, Skill>>("LuaCollectSummonAttack"); luaCollectGhostSkill = luaEnv.Global.Get<Action<Actor, Skill>>("LuaCollectGhostSkill"); luaCollectAttack = luaEnv.Global.Get<Action<Actor, Skill>>("LuaCollectAttack"); luaCollectHurtState = luaEnv.Global.Get<Action<Actor, int>>("LuaCollectHurtState"); luaCollectHurtData = luaEnv.Global.Get<Action<EffectResult, Actor>>("LuaCollectHurtData"); luaCollectCommandLittleMonsterHurtRole = luaEnv.Global.Get<Action<EffectResult, Actor>>("LuaCollectCommandLittleMonsterHurtRole"); luaCollectChangePetHost = luaEnv.Global.Get<Action<int, long, int, Vector3>>("LuaCollectChangePetHost"); luaCollectSoul = luaEnv.Global.Get<Action<Actor, int>>("LuaCollectSoul"); luaCollectSpecialBuff = luaEnv.Global.Get<luaCollectSpecialBuff>("LuaCollectSpecialBuff"); luaGetActorId = luaEnv.Global.Get<Func<Actor, Message.ActorId>>("LuaGetActorId"); luaCheckNeedCollectHurtData = luaEnv.Global.Get<Func<Actor, Actor, bool>>("LuaCheckNeedCollectHurtData"); luaCheckNeedCollect = luaEnv.Global.Get<Func<Actor, bool>>("LuaCheckNeedCollect"); luaNeedCommandLittleMonsterHurtRole = luaEnv.Global.Get<Func<Actor, Actor, bool>>("LuaNeedCommandLittleMonsterHurtRole");
|
执行lua的main脚本,也是lua端的总入口。
运行平台的判断。
获取Lua测的函数。
1 2 3 4 5 6
| if (startFunc != null) { startFunc.Call(ios, android, editor, dalu, taiwan, appstore, ttsdk, xianxing); startFunc.Dispose(); startFunc = null; }
|
object[] Call(params object[] args) : 以可变参数调用Lua函数,并返回该调用的返回值。
紧接着调用main.lua的LuaStart函数。
以下都在lua层,我们暂时只看热更相关的内容。
main.lua的LuaStart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function LuaStart(ios, android, editor, appStore) print("LuaStart", ios, android, editor,appStore) Global.IOS = ios Global.Android = android Global.Editor = editor Global.BT = false; Global.ChangeTime = "" Global.Writer = "" AppStore = appStore CS.ReConnectUtils.NetworkOutTime = 0.1 Register.RegisterWindow() LuaFix() RegisterLuaGameState() LuaInit() end
|
LuaFix()
1 2 3 4 5 6
| function LuaFix() if FixList.HasFix() then FixList.InitFix() end return FixList.HasFix() end
|
如果是开启热更状态,会初始化热更。
InitFix()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| function FixList.InitFix() require "xlua.util"
require "HotfixLoginMainFinal" require "HotfixPanelBaozangZuanshiXuanze" require "HotfixWindowWildMissionDetail"
…… …… …… …… ……
require "HotfixMissionService" require "HotfixPanelRiverGod"
require "OldRedDotWindow" require "HotfixEnvironmentService" require "HotfixLogin" require "HotfixBattleWindow" require "HotfixGameConfig" require "HotfixWindowInNewMainCity"
require "HotfixAddSpeed" require "HotfixPractice" require "HotfixTask"
require "HotfixAttackUtils" require "HotfixVip" require "HotfixSuperManService" require "HotfixPrayShopCellItem" end
|
此处省略一万个require,我们看一个热修复作为示例。
HotfixWindowManager
1 2 3 4 5 6 7 8 9 10 11 12 13
| local util = require "xlua.util"
xlua.private_accessible(CS.WindowManager)
util.hotfix_ex( CS.WindowManager, "isShouldExit", function(self) if(Global.IsAnimation) then return false end self:isShouldExit() end )
|