XLua 热更新方案

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下或在检测版本后激活该脚本) 

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XLua;

public class FishHotFix_Inlet : MonoBehaviour
{
    LuaEnv luaenv = null;

    void Start()
    {
        luaenv = new LuaEnv();

        //luaenv.DoString("print('hello world')");


        //luaenv.DoString("require 'fishHotFixPrint'");


        //luaenv.DoString(@"
        //    xlua.hotfix(CS.Inlet, 'FTest', function(self)
        //        print('inlet .. hotfix .. FTest')
        //    end)
        //");


        //luaenv.DoString("require 'fishHotFix'");


        //luaenv.AddLoader((ref string filename) =>
        //{
        //    if (filename == "fishHotFix")
        //    {
        //        string path = @"C:\Users\User\Desktop\XLua\fishHotFix.lua.txt";
        //        return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(path));
        //    }
        //    return null;
        //});
        //luaenv.DoString("require 'fishHotFix'");

        luaenv.AddLoader(MyLoader);//加载.lua文件
        luaenv.DoString("require 'fishHotFix'");//执行HotFix.lua
    }

    private byte[] MyLoader(ref string filePath)
    {
        //string path = @"C:\Users\User\Desktop\XLua\" + filePath + ".lua.txt";
        string path = Application.streamingAssetsPath + "/fishhotfix/" + filePath + ".lua.txt";
        return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(path));
    }

    void Update()
    {
        if (luaenv != null)
        {
            luaenv.Tick();
        }
    }

    void OnDestroy()
    {
        //luaenv Dispose之前注销
        //HotFixDispose.lua,注销lua执行方法
        luaenv.DoString("require 'fishHotFixDispose'");
        luaenv.Dispose();
    }
}

4、自动识别文件配置[Hotfix]、lua调用C#、C#调用lua(放到Assets\XLua\Editor目录下)

using System.Collections.Generic;
using System;
using XLua;
using System.Reflection;
using System.Linq;
using UnityEngine;

public static class HotFixConfig
{
    //筛选过的文件具有热更功能==类名添加[Hotfix]
    [Hotfix]
    public static List<Type> by_property
    {
        // X:\lemongame\slgrpg_2d\3d\slgrogue\Assets\ProjectTemplate\Plugins\Sirenix\Assemblies\Sirenix.OdinInspector.Editor.dll
        get
        {
            return (from type in Assembly.Load("Assembly-CSharp").GetTypes()
                    where type.Namespace == null || !type.Namespace.StartsWith("XLua")
                    select type).ToList();//文件筛选
        }
    }

    //lua中要使用到C#库的配置,比如C#标准库,或者Unity API,第三方库等。
    [LuaCallCSharp]
    public static List<Type> LuaCallCSharp = new List<Type>() {
                typeof(System.Object),
                typeof(UnityEngine.Object),
                typeof(Vector2),
                typeof(Vector3),
                typeof(Vector4),
                typeof(Quaternion),
                typeof(Color),
                typeof(Ray),
                typeof(Bounds),
                typeof(Ray2D),
                typeof(Time),
                typeof(GameObject),
                typeof(Component),
                typeof(Behaviour),
                typeof(Transform),
                typeof(Resources),
                typeof(TextAsset),
                typeof(Keyframe),
                typeof(AnimationCurve),
                typeof(AnimationClip),
                typeof(MonoBehaviour),
                typeof(ParticleSystem),
                typeof(SkinnedMeshRenderer),
                typeof(Renderer),
                typeof(WWW),
                //typeof(Light),
                typeof(Mathf),
                typeof(System.Collections.Generic.List<int>),
                typeof(Action<string>),
                typeof(UnityEngine.Debug)
            };

    //C#静态调用Lua的配置(包括事件的原型),仅可以配delegate,interface
    [CSharpCallLua]
    public static List<Type> CSharpCallLua = new List<Type>() {
                typeof(Action),
                typeof(Func<double, double, double>),
                typeof(Action<string>),
                typeof(Action<double>),
                typeof(UnityEngine.Events.UnityAction),
                typeof(System.Collections.IEnumerator)
            };

    //黑名单
    [BlackList]
    public static List<List<string>> BlackList = new List<List<string>>()  {
                new List<string>(){"System.Xml.XmlNodeList", "ItemOf"},
                new List<string>(){"UnityEngine.WWW", "movie"},
    #if UNITY_WEBGL
                new List<string>(){"UnityEngine.WWW", "threadPriority"},
    #endif
                new List<string>(){"UnityEngine.Texture2D", "alphaIsTransparency"},
                new List<string>(){"UnityEngine.Security", "GetChainOfTrustValue"},
                new List<string>(){"UnityEngine.CanvasRenderer", "onRequestRebuild"},
                //new List<string>(){"UnityEngine.Light", "areaSize"},
                //new List<string>(){"UnityEngine.Light", "lightmapBakeType"},
                //new List<string>(){"UnityEngine.Light", "shadowAngle"},
                //new List<string>(){"UnityEngine.Light", "shadowRadius"},
                //new List<string>(){"UnityEngine.Light", "SetLightDirty"},
                new List<string>(){"UnityEngine.WWW", "MovieTexture"},
                new List<string>(){"UnityEngine.WWW", "GetMovieTexture"},
                new List<string>(){"UnityEngine.AnimatorOverrideController", "PerformOverrideClipListCleanup"},
    #if !UNITY_WEBPLAYER
                new List<string>(){"UnityEngine.Application", "ExternalEval"},
    #endif
                new List<string>(){"UnityEngine.GameObject", "networkView"}, //4.6.2 not support
                new List<string>(){"UnityEngine.Component", "networkView"},  //4.6.2 not support
                new List<string>(){"System.IO.FileInfo", "GetAccessControl", "System.Security.AccessControl.AccessControlSections"},
                new List<string>(){"System.IO.FileInfo", "SetAccessControl", "System.Security.AccessControl.FileSecurity"},
                new List<string>(){"System.IO.DirectoryInfo", "GetAccessControl", "System.Security.AccessControl.AccessControlSections"},
                new List<string>(){"System.IO.DirectoryInfo", "SetAccessControl", "System.Security.AccessControl.DirectorySecurity"},
                new List<string>(){"System.IO.DirectoryInfo", "CreateSubdirectory", "System.String", "System.Security.AccessControl.DirectorySecurity"},
                new List<string>(){"System.IO.DirectoryInfo", "Create", "System.Security.AccessControl.DirectorySecurity"},
                new List<string>(){"UnityEngine.MonoBehaviour", "runInEditMode"},
            };


#if UNITY_2018_1_OR_NEWER
    [BlackList]
    public static Func<MemberInfo, bool> MethodFilter = (memberInfo) =>
    {
        if (memberInfo.DeclaringType.IsGenericType && memberInfo.DeclaringType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
        {
            if (memberInfo.MemberType == MemberTypes.Constructor)
            {
                ConstructorInfo constructorInfo = memberInfo as ConstructorInfo;
                var parameterInfos = constructorInfo.GetParameters();
                if (parameterInfos.Length > 0)
                {
                    if (typeof(System.Collections.IEnumerable).IsAssignableFrom(parameterInfos[0].ParameterType))
                    {
                        return true;
                    }
                }
            }
            else if (memberInfo.MemberType == MemberTypes.Method)
            {
                var methodInfo = memberInfo as MethodInfo;
                if (methodInfo.Name == "TryAdd" || methodInfo.Name == "Remove" && methodInfo.GetParameters().Length == 2)
                {
                    return true;
                }
            }
        }
        return false;
    };
#endif
}

5、Asset/StreamingAssets的lua文件(测试lua是否执行修改原有C#逻辑,可以按具体项目来编写)
(1)fishHotFix.lua.txt

local util = require '../../XLua/Resources/xlua/util'

--1、执行新的逻辑
xlua.hotfix(CS.FUIWindow_CoverUIVO, 'FTest', function(self)
	CS.UnityEngine.Debug.Log("hotfix .. FTest .. by .. streamingAssetsPath .. lua")
end)


--2、执行原来的逻辑
util.hotfix_ex(CS.FUIWindow_CoverUIVO, 'FTest1', function(self)
	self:FTest1()
	CS.UnityEngine.Debug.Log("hotfix .. FUIWindow_CoverUIVO .. FTest .. 1")
end)


--3、执行协程
xlua.hotfix(CS.FUIWindow_CoverUIVO, 'FIEnumTest', function(self)
	return util.cs_generator(function()
		print('hotfix .. FIEnumTest .. start')
		coroutine.yield(CS.UnityEngine.WaitForSeconds(3))
		print('hotfix .. FIEnumTest .. 3f')
	end)
end)


--4、修改界面控件逻辑
xlua.hotfix(CS.FUIWindow_CoverUIVO, 'SetLoginType', function(self, login)
	print('hotfix .. SetLoginType .. login =', login, not login)
	self._fui.m_btn_login.visible = login
    self._fui.m_progressbar.visible = not login
	self._fui.m_text.visible = not login
	print('hotfix .. SetLoginType ..')
end)


--5、修改界面逻辑(注意添加CS,调用属性和方法)
util.hotfix_ex(CS.FUIWindow_MainTopUIVO, 'UpdateCurrency', function(self, notif)
	self:UpdateCurrency(notif)
	self._fui.m_Com_gold.m_title.text = 100
end)


--6、同级目录下lua逻辑
require 'fishHotFixPrint'

 

 (2)fishHotFixPrint.lua.txt

local util = require '../../XLua/Resources/xlua/util'

--修改(可以覆盖之前的)
util.hotfix_ex(CS.FUIWindow_MainTopUIVO, 'UpdateCurrency', function(self, notif)
	self:UpdateCurrency(notif)
	self._fui.m_Com_gold.m_title.text = 100
	self._fui.m_Com_diamond.m_title.text = CS.UserInfo.Instance:GetCurrency(CS.CurrencyType.diamond) + 100
end)

 

 (3)fishHotFixDispose.lua.txt 

--在LuaEnv Dispose之前注销
xlua.hotfix(CS.FUIWindow_CoverUIVO,'FTest',nil)
xlua.hotfix(CS.FUIWindow_CoverUIVO,'FTest1',nil)
xlua.hotfix(CS.FUIWindow_CoverUIVO,'FIEnumTest',nil)
xlua.hotfix(CS.FUIWindow_CoverUIVO,'SetLoginType',nil)
xlua.hotfix(CS.FUIWindow_MainTopUIVO,'UpdateCurrency',nil)

 

6、Lua和C#的连接(不修改HotFixConfig配置文件不需要执行1、2步)
(1)清除C#和lua链接文件;
(2)生成链接的中间文件;
(3)注入(Unity启动游戏时,注入成功弹窗)

注入成功提示 
 

7、使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值