热更新应用--热补丁Hotfix学习笔记

一.热补丁简介html

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

二.第一个热补丁函数

  1.C#代码端:学习

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

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

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端代码this

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

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

require("Hotfix1")

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

--热补丁

--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
})
相关文章
相关标签/搜索