找回密码
 立即注册
查看: 298|回复: 0

XLua 热更新方案

[复制链接]
发表于 2021-8-14 13:39 | 显示全部楼层 |阅读模式
1、下载XLua最新框架zip(https://github.com/Tencent/xLua)
2、导入最新的XLua框架(按文件原始路径,导入Plugins、XLua、Tool三个文件)
(1)项目Asset目录下导入Plugings和XLua;
(2)Asset同级目录下导入Tool工具;
(3)开启宏 HOTFIX_ENABLE,File---->buildSetting---->playerSetting---->scriptsDefineSymbols里添加;HOTFIX_ENABLE。(注意 :编辑器、各手机平台这个宏要分别设置!如果是自动化打包,要注意在代码里头用API设置的宏是不生效的,需要在编辑器设置)


3、C#逻辑下热更新逻辑入口(可以放在Camera下或在检测版本后激活该脚本)
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using UnityEngine;
  5. using XLua;
  6. public class FishHotFix_Inlet : MonoBehaviour
  7. {
  8.     LuaEnv luaenv = null;
  9.     void Start()
  10.     {
  11.         luaenv = new LuaEnv();
  12.         //luaenv.DoString("print('hello world')");
  13.         //luaenv.DoString("require 'fishHotFixPrint'");
  14.         //luaenv.DoString(@"
  15.         //    xlua.hotfix(CS.Inlet, 'FTest', function(self)
  16.         //        print('inlet .. hotfix .. FTest')
  17.         //    end)
  18.         //");
  19.         //luaenv.DoString("require 'fishHotFix'");
  20.         //luaenv.AddLoader((ref string filename) =>
  21.         //{
  22.         //    if (filename == "fishHotFix")
  23.         //    {
  24.         //        string path = @"C:\Users\User\Desktop\XLua\fishHotFix.lua.txt";
  25.         //        return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(path));
  26.         //    }
  27.         //    return null;
  28.         //});
  29.         //luaenv.DoString("require 'fishHotFix'");
  30.         luaenv.AddLoader(MyLoader);//加载.lua文件
  31.         luaenv.DoString("require 'fishHotFix'");//执行HotFix.lua
  32.     }
  33.     private byte[] MyLoader(ref string filePath)
  34.     {
  35.         //string path = @"C:\Users\User\Desktop\XLua" + filePath + ".lua.txt";
  36.         string path = Application.streamingAssetsPath + "/fishhotfix/" + filePath + ".lua.txt";
  37.         return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(path));
  38.     }
  39.     void Update()
  40.     {
  41.         if (luaenv != null)
  42.         {
  43.             luaenv.Tick();
  44.         }
  45.     }
  46.     void OnDestroy()
  47.     {
  48.         //luaenv Dispose之前注销
  49.         //HotFixDispose.lua,注销lua执行方法
  50.         luaenv.DoString("require 'fishHotFixDispose'");
  51.         luaenv.Dispose();
  52.     }
  53. }
复制代码
4、自动识别文件配置[Hotfix]、lua调用C#、C#调用lua(放到Assets\XLua\Editor目录下)
  1. using System.Collections.Generic;
  2. using System;
  3. using XLua;
  4. using System.Reflection;
  5. using System.Linq;
  6. using UnityEngine;
  7. public static class HotFixConfig
  8. {
  9.     //筛选过的文件具有热更功能==类名添加[Hotfix]
  10.     [Hotfix]
  11.     public static List<Type> by_property
  12.     {
  13.         // X:\lemongame\slgrpg_2d\3d\slgrogue\Assets\ProjectTemplate\Plugins\Sirenix\Assemblies\Sirenix.OdinInspector.Editor.dll
  14.         get
  15.         {
  16.             return (from type in Assembly.Load("Assembly-CSharp").GetTypes()
  17.                     where type.Namespace == null || !type.Namespace.StartsWith("XLua")
  18.                     select type).ToList();//文件筛选
  19.         }
  20.     }
  21.     //lua中要使用到C#库的配置,比如C#标准库,或者Unity API,第三方库等。
  22.     [LuaCallCSharp]
  23.     public static List<Type> LuaCallCSharp = new List<Type>() {
  24.                 typeof(System.Object),
  25.                 typeof(UnityEngine.Object),
  26.                 typeof(Vector2),
  27.                 typeof(Vector3),
  28.                 typeof(Vector4),
  29.                 typeof(Quaternion),
  30.                 typeof(Color),
  31.                 typeof(Ray),
  32.                 typeof(Bounds),
  33.                 typeof(Ray2D),
  34.                 typeof(Time),
  35.                 typeof(GameObject),
  36.                 typeof(Component),
  37.                 typeof(Behaviour),
  38.                 typeof(Transform),
  39.                 typeof(Resources),
  40.                 typeof(TextAsset),
  41.                 typeof(Keyframe),
  42.                 typeof(AnimationCurve),
  43.                 typeof(AnimationClip),
  44.                 typeof(MonoBehaviour),
  45.                 typeof(ParticleSystem),
  46.                 typeof(SkinnedMeshRenderer),
  47.                 typeof(Renderer),
  48.                 typeof(WWW),
  49.                 //typeof(Light),
  50.                 typeof(Mathf),
  51.                 typeof(System.Collections.Generic.List<int>),
  52.                 typeof(Action<string>),
  53.                 typeof(UnityEngine.Debug)
  54.             };
  55.     //C#静态调用Lua的配置(包括事件的原型),仅可以配delegate,interface
  56.     [CSharpCallLua]
  57.     public static List<Type> CSharpCallLua = new List<Type>() {
  58.                 typeof(Action),
  59.                 typeof(Func<double, double, double>),
  60.                 typeof(Action<string>),
  61.                 typeof(Action<double>),
  62.                 typeof(UnityEngine.Events.UnityAction),
  63.                 typeof(System.Collections.IEnumerator)
  64.             };
  65.     //黑名单
  66.     [BlackList]
  67.     public static List<List<string>> BlackList = new List<List<string>>()  {
  68.                 new List<string>(){"System.Xml.XmlNodeList", "ItemOf"},
  69.                 new List<string>(){"UnityEngine.WWW", "movie"},
  70.     #if UNITY_WEBGL
  71.                 new List<string>(){"UnityEngine.WWW", "threadPriority"},
  72.     #endif
  73.                 new List<string>(){"UnityEngine.Texture2D", "alphaIsTransparency"},
  74.                 new List<string>(){"UnityEngine.Security", "GetChainOfTrustValue"},
  75.                 new List<string>(){"UnityEngine.CanvasRenderer", "onRequestRebuild"},
  76.                 //new List<string>(){"UnityEngine.Light", "areaSize"},
  77.                 //new List<string>(){"UnityEngine.Light", "lightmapBakeType"},
  78.                 //new List<string>(){"UnityEngine.Light", "shadowAngle"},
  79.                 //new List<string>(){"UnityEngine.Light", "shadowRadius"},
  80.                 //new List<string>(){"UnityEngine.Light", "SetLightDirty"},
  81.                 new List<string>(){"UnityEngine.WWW", "MovieTexture"},
  82.                 new List<string>(){"UnityEngine.WWW", "GetMovieTexture"},
  83.                 new List<string>(){"UnityEngine.AnimatorOverrideController", "PerformOverrideClipListCleanup"},
  84.     #if !UNITY_WEBPLAYER
  85.                 new List<string>(){"UnityEngine.Application", "ExternalEval"},
  86.     #endif
  87.                 new List<string>(){"UnityEngine.GameObject", "networkView"}, //4.6.2 not support
  88.                 new List<string>(){"UnityEngine.Component", "networkView"},  //4.6.2 not support
  89.                 new List<string>(){"System.IO.FileInfo", "GetAccessControl", "System.Security.AccessControl.AccessControlSections"},
  90.                 new List<string>(){"System.IO.FileInfo", "SetAccessControl", "System.Security.AccessControl.FileSecurity"},
  91.                 new List<string>(){"System.IO.DirectoryInfo", "GetAccessControl", "System.Security.AccessControl.AccessControlSections"},
  92.                 new List<string>(){"System.IO.DirectoryInfo", "SetAccessControl", "System.Security.AccessControl.DirectorySecurity"},
  93.                 new List<string>(){"System.IO.DirectoryInfo", "CreateSubdirectory", "System.String", "System.Security.AccessControl.DirectorySecurity"},
  94.                 new List<string>(){"System.IO.DirectoryInfo", "Create", "System.Security.AccessControl.DirectorySecurity"},
  95.                 new List<string>(){"UnityEngine.MonoBehaviour", "runInEditMode"},
  96.             };
  97. #if UNITY_2018_1_OR_NEWER
  98.     [BlackList]
  99.     public static Func<MemberInfo, bool> MethodFilter = (memberInfo) =>
  100.     {
  101.         if (memberInfo.DeclaringType.IsGenericType && memberInfo.DeclaringType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
  102.         {
  103.             if (memberInfo.MemberType == MemberTypes.Constructor)
  104.             {
  105.                 ConstructorInfo constructorInfo = memberInfo as ConstructorInfo;
  106.                 var parameterInfos = constructorInfo.GetParameters();
  107.                 if (parameterInfos.Length > 0)
  108.                 {
  109.                     if (typeof(System.Collections.IEnumerable).IsAssignableFrom(parameterInfos[0].ParameterType))
  110.                     {
  111.                         return true;
  112.                     }
  113.                 }
  114.             }
  115.             else if (memberInfo.MemberType == MemberTypes.Method)
  116.             {
  117.                 var methodInfo = memberInfo as MethodInfo;
  118.                 if (methodInfo.Name == "TryAdd" || methodInfo.Name == "Remove" && methodInfo.GetParameters().Length == 2)
  119.                 {
  120.                     return true;
  121.                 }
  122.             }
  123.         }
  124.         return false;
  125.     };
  126. #endif
  127. }
复制代码
5、Asset/StreamingAssets的lua文件(测试lua是否执行修改原有C#逻辑,可以按具体项目来编写)
(1)fishHotFix.lua.txt
  1. local util = require '../../XLua/Resources/xlua/util'
  2. --1、执行新的逻辑
  3. xlua.hotfix(CS.FUIWindow_CoverUIVO, 'FTest', function(self)
  4.         CS.UnityEngine.Debug.Log("hotfix .. FTest .. by .. streamingAssetsPath .. lua")
  5. end)
  6. --2、执行原来的逻辑
  7. util.hotfix_ex(CS.FUIWindow_CoverUIVO, 'FTest1', function(self)
  8.         self:FTest1()
  9.         CS.UnityEngine.Debug.Log("hotfix .. FUIWindow_CoverUIVO .. FTest .. 1")
  10. end)
  11. --3、执行协程
  12. xlua.hotfix(CS.FUIWindow_CoverUIVO, 'FIEnumTest', function(self)
  13.         return util.cs_generator(function()
  14.                 print('hotfix .. FIEnumTest .. start')
  15.                 coroutine.yield(CS.UnityEngine.WaitForSeconds(3))
  16.                 print('hotfix .. FIEnumTest .. 3f')
  17.         end)
  18. end)
  19. --4、修改界面控件逻辑
  20. xlua.hotfix(CS.FUIWindow_CoverUIVO, 'SetLoginType', function(self, login)
  21.         print('hotfix .. SetLoginType .. login =', login, not login)
  22.         self._fui.m_btn_login.visible = login
  23.     self._fui.m_progressbar.visible = not login
  24.         self._fui.m_text.visible = not login
  25.         print('hotfix .. SetLoginType ..')
  26. end)
  27. --5、修改界面逻辑(注意添加CS,调用属性和方法)
  28. util.hotfix_ex(CS.FUIWindow_MainTopUIVO, 'UpdateCurrency', function(self, notif)
  29.         self:UpdateCurrency(notif)
  30.         self._fui.m_Com_gold.m_title.text = 100
  31. end)
  32. --6、同级目录下lua逻辑
  33. require 'fishHotFixPrint'
复制代码
(2)fishHotFixPrint.lua.txt
  1. local util = require '../../XLua/Resources/xlua/util'
  2. --修改(可以覆盖之前的)
  3. util.hotfix_ex(CS.FUIWindow_MainTopUIVO, 'UpdateCurrency', function(self, notif)
  4.         self:UpdateCurrency(notif)
  5.         self._fui.m_Com_gold.m_title.text = 100
  6.         self._fui.m_Com_diamond.m_title.text = CS.UserInfo.Instance:GetCurrency(CS.CurrencyType.diamond) + 100
  7. end)
复制代码
(3)fishHotFixDispose.lua.txt
  1. --在LuaEnv Dispose之前注销
  2. xlua.hotfix(CS.FUIWindow_CoverUIVO,'FTest',nil)
  3. xlua.hotfix(CS.FUIWindow_CoverUIVO,'FTest1',nil)
  4. xlua.hotfix(CS.FUIWindow_CoverUIVO,'FIEnumTest',nil)
  5. xlua.hotfix(CS.FUIWindow_CoverUIVO,'SetLoginType',nil)
  6. xlua.hotfix(CS.FUIWindow_MainTopUIVO,'UpdateCurrency',nil)
复制代码
6、Lua和C#的连接(不修改HotFixConfig配置文件不需要执行1、2步)
(1)清除C#和lua链接文件;
(2)生成链接的中间文件;
(3)注入(Unity启动游戏时,注入成功弹窗)



注入成功提示



7、使用

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 11:49 , Processed in 0.092817 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表