zoukankan      html  css  js  c++  java
  • 热更新应用--热补丁Hotfix学习笔记

    一.热补丁简介

      热补丁主要是用于将纯C#工程在不重做的情况下通过打补丁的形式改造成具备lua热更新功能工程,主要是让原来脚本中Start函数和Update函数等函数代码块重定向到lua代码。

    二.第一个热补丁

      1.C#代码端:

        1)创建一个脚本,并挂载到游戏中的任意物体上(实际使用过程中一般修改已有脚本,这里测试随意挂载就好)

        2)在脚本中定义好测试用的方法,在Start函数中执行Lua文件(LuaManager类及C#调用lua代码的方式详见xlua学习笔记,LuaManager类在:四.C#调用lua-3.lua解析器管理器)

    public class HotfixMain : MonoBehaviour
    {
        void Start()
        {
            LuaManager.Instance.DoLuaFile("Main");
    
            //调用定义的方法,这些方法被lua中的热补丁重新定义了
            Debug.Log(Add(1, 2));
            Speak("我很帅");
        }
    
        //预备给热补丁覆盖的成员方法
        public int Add(int a,int b)
        {
            return 0;
        }
        //预备给热补丁覆盖的静态方法
        public static void Speak(string str)
        {
            Debug.Log("hahaha");
        }
    }

      2.lua端代码

        1)将lua文件放在LuaManager类能够重定向到的文件夹中,或者添加LuaManager类中的重定向方法使lua文件能被找到,这里放在Assets目录下的Lua文件夹下,LuaManager中已经添加了这个文件的重定向方法。

        2).C#代码调用了Main,所以在文件夹中添加Main.lua这个lua文件,这个文件使lua的主入口文件,相当于C#工程中的Main方法,主要用于执行其他lua文件、定义一些通用全局变量、初始化等。这里Main文件中执行Hotfix1文件,代码就一句:

    require("Hotfix1")

        3)Hotfix1.lua文件中定义第一个热补丁的代码,主要调用方法xlu.hotfix重写C#中的方法:

    --热补丁
    
    --lua中的热补丁固定写法
    --通过xlua的hotfix函数进行热补丁更新,参数是:类名、"函数名",lua函数
    
    --成员方法将self作为第一个参数传入
    xlua.hotfix(CS.HotfixMain,"Add",function(self,a,b)
        return a + b
    end)
    --静态方法不需要传入self参数
    xlua.hotfix(CS.HotfixMain,"Speak",function(a)
        print(a)
    end)
    
    --热补丁还需要在Unity脚本中作以下操作
    --加特性、加宏、生成代码、hotfix注入
    
    --热补丁缺陷:只要修改了热补丁的代码,都需要重新做hotfix注入

      3.Unity中的操作

        1)加特性:在需要被热补丁更新的C#类前面加上[Hotfix]特性,这里给刚才1中创建的脚本加上特性,其他非mono脚本也是一样的做法:

    //加上特性以生成热补丁代码
    [Hotfix]
    public class HotfixMain : MonoBehaviour
    {
        void Start()
        {
            LuaManager.Instance.DoLuaFile("Main");
    
            //调用定义的方法,这些方法被lua中的热补丁重新定义了
            Debug.Log(Add(1, 2));
            Speak("我很帅");
        }
    
        //预备给热补丁覆盖的成员方法
        public int Add(int a,int b)
        {
            return 0;
        }
        //预备给热补丁覆盖的静态方法
        public static void Speak(string str)
        {
            Debug.Log("hahaha");
        }
    }

        2)加宏:打开Unity中Edit->ProjectSetting

          在Player->otherSetting->Scripting Define Symbols中输入HOTFIX_ENABLE

        3)加宏之后生成代码,点击XLua选项下Generate Code选项生成代码。注意:加宏成功后XLua选项下会出现Hotfix Inject In Editor选项,这个是hotfix注入使用的选项,如果没有的话说明刚才的宏没有成功加上。

        4)点击Hotfix Inject In Editor进行hotfix注入,如果报错please install the Tools,将xlua工程源文件中的Tools文件夹拷贝到自己的工程中。注意:不是拷贝到Assets目录下,源工程文件夹中Tools文件夹和Assets文件夹同级,所以将Tools文件夹拷贝到自己的工程文件中和Assets文件夹同级文件夹下而不是Assets目录下(三张图片分别是xlua源文件夹中Tools文件夹所在位置、打开工程所在文件夹、拷贝后在自己的工程中Tools文件夹所在位置):

        5)运行工程

      4.最后:注意每次热补丁的代码修改后,都需要重新生成代码和hotfix注入。

    三.hotfix重定向其他内容

      1.多函数替换和构造析构函数热补丁(构造函数和析构函数重定向后原代码逻辑会先执行,再执行lua中重定向的代码逻辑,这一点和其他成员函数及静态函数不同)

    //加上特性以生成热补丁代码
    [Hotfix]
    public class HotfixMain : MonoBehaviour
    {
        void Start()
        {
            LuaManager.Instance.DoLuaFile("Main");
    
            //调用定义的方法,这些方法被lua中的热补丁重新定义了
            Debug.Log(Add(1, 2));
            Speak("我很帅");
        }
    
        private void Update()
        {
            
        }
    
        //预备给热补丁覆盖的成员方法
        public int Add(int a,int b)
        {
            return 0;
        }
        //预备给热补丁覆盖的静态方法
        public static void Speak(string str)
        {
            Debug.Log("hahaha");
        }
    }
    
    [Hotfix]
    public class HotfixTest
    {
        public HotfixTest()
        {
            Debug.Log("HotfixTest构造函数");
        }
        public void Speak(string str)
        {
            Debug.Log(str);
        }
        ~HotfixTest()
        {
    
        }
    }
    --多函数替换
    --将多个函数写成一个表作为参数传入
    xlua.hotfix(CS.HotfixMain,{
        Update = function(self)
            print(os.time())
        end,
        Add = function(self,a,b)
            return a + b
        end,
        Speak = function(a)
            print(a)
        end
    })
    
    --构造函数热补丁
    xlua.hotfix(CS.HotfixTest,{
        --构造函数的热补丁固定写法
        [".ctor"] = function()
            print("Lua热补丁构造函数")
        end,
        Speak = function(self,a)
            print("Lua热补丁Speak函数")
        end,
        --析构函数的热补丁固定写法
        Finalize = function()
            print("Lua热补丁析构函数")
        end
    })

      2.协程函数替换

    [Hotfix]
    public class HotfixMain : MonoBehaviour
    {
        void Start()
        {
            LuaManager.Instance.DoLuaFile("Main");
    
            StartCoroutine(TestCoroutine());
        }
    
        IEnumerator TestCoroutine()
        {
            while (true)
            {
                yield return new WaitForSeconds(1f);
                Debug.Log("c#协程打印一次");
            }
        }
    }
    --协程函数替换
    
    --使用协程必须引入xlua.util
    util = require("xlua.util")
    
    
    xlua.hotfix(CS.HotfixMain,{
        TestCoroutine = function(self)
            return util.cs_generator(function()
                while true do
                    coroutine.yield(CS.UnityEngine.WaitForSeconds(1))
                    print("lua热补丁协程函数")
                end
            end)
        end
    })

      3.索引器和属性替换

    [Hotfix]
    public class HotfixMain : MonoBehaviour
    {
        private int[] array = new int[] { 5, 4, 3, 2, 1 };
        void Start()
        {
            LuaManager.Instance.DoLuaFile("Main");
    
            Debug.Log(this.Age);
            this.Age = 200;
            Debug.Log(this[0]);
            this[2] = 10000;
        }
    
        //定义属性
        public int Age
        {
            get
            {
                return 0;
            }
            set
            {
                Debug.Log(value);
            }
        }
        //定义索引器
        public int this[int index]
        {
            get
            {
                if (index >= 0 && index < 5)
                    return array[index];
                return 0;
            }
            set
            {
                if (index >= 0 && index < 5)
                    array[index] = value;
            }
    
        }
    }
    xlua.hotfix(CS.HotfixMain,{
        --属性热补丁的固定写法
        --使用set_属性名替换设置属性的方法,使用get_属性名替换获取属性值的方法
        set_Age = function(self,v)
            print("Lua热补丁设置属性")
        end,
        get_Age = function(self)
            return 10
        end,
        --索引器在类中是唯一的,固定写法和属性类似
        --使用set_Item替换索引器的set方法,使用get_Item替换索引器的set方法
        get_Item = function(self,index)
            print("Lua热补丁重定向索引器get")
            return 1000;
        end,
        set_Item = function(self,index,v)
            print("Lua热补丁重定向索引器set")
        end
    })

      4.事件替换

    [Hotfix]
    public class HotfixMain : MonoBehaviour
    {
        event UnityAction customEvent;
        void Start()
        {
            LuaManager.Instance.DoLuaFile("Main");
    
            StartCoroutine(EventAddRemove());
        }
        private void Update()
        {
            if (customEvent != null)
                customEvent();
        }
        /// <summary>
        /// 添加到委托中的函数
        /// </summary>
        private void Test()
        {
            Debug.Log("event test running");
        }
        /// <summary>
        /// 使用协程添加和删除委托函数
        /// </summary>
        /// <returns></returns>
        private IEnumerator EventAddRemove()
        {
            customEvent += Test;
            yield return new WaitForSeconds(5f);
            customEvent -= Test;
        }
    }
    --事件热补丁
    
    xlua.hotfix(CS.HotfixMain,{
        --add_事件名 代表添加事件
        --remove_事件名 代表移除事件
        add_customEvent = function(self,del)
            print(del)
            print("添加事件函数")
            --在添加事件时,不要把传入的委托往事件中存,否则会死循环
            --self:customEvent("+",del)
        end,
        remove_customEvent = function(self,del)
            print(del)
            print("移除事件函数")
        end
    })

      5.泛型类替换

    [Hotfix]
    public class HotfixTest2<T>
    {
        public void Test(T str)
        {
            Debug.Log(str);
        }
    }
        void Start()
        {
            LuaManager.Instance.DoLuaFile("Main");
    
            new HotfixTest2<string>().Test("movin");
            new HotfixTest2<int>().Test(10000);
        }
    --泛型类中泛型T可以变化,所以要一个类型一个类型地替换
    --在第一个参数后面加上括号,括号中书写一个类型,代表如果泛型是这个类型时地替换方法
    xlua.hotfix(CS.HotfixTest2(CS.System.String),{
        Test = function(self,str)
            print("泛型为string时的热补丁,参数是"..str)
        end
    })
    xlua.hotfix(CS.HotfixTest2(CS.System.Int32),{
        Test = function(self,i)
            print("泛型为int时的热补丁,参数是"..i)
        end
    })

        

  • 相关阅读:
    Nagios显示器mysql定从库: libmysqlclient.so.18: cannot open shared object file: No such
    UVA 11402
    Oracle 11g 的PL/SQL函数结果缓存
    最大公约数(Greatest Common Divisor)
    计时器 Timer
    ArcGIS Engine 捕捉
    AE+C# 图层中增加相应属性标注
    C# ComboBox自动完成功能的示例
    Visual Assist的破解与安装
    GitHub的代码托管和使用方法
  • 原文地址:https://www.cnblogs.com/movin2333/p/14628735.html
Copyright © 2011-2022 走看看