Unity Hotfix(热补丁)

发布于:2025-03-04 ⋅ 阅读:(22) ⋅ 点赞:(0)

目录

前言

使用Hotfix

1.加特性

2.加宏

​编辑3.生成代码

​编辑4.hotfix注入

实现效果

多函数替换

协程函数替换

索引器替换

事件替换

泛型替换


前言

         在Unity游戏开发中,热补丁(Hotfix)技术扮演着至关重要的角色。随着游戏版本的迭代和更新,开发者们常常会遇到一些在发布后才发现的bug或需要紧急修复的问题。传统的修复方式往往需要重新发布游戏版本,这不仅耗时长,还可能对用户体验造成不良影响。而热补丁技术的出现,为这些问题提供了一种快速、灵活的解决方案。

        热补丁,通俗理解就是将C#中的方法替换成Lua等脚本语言中的函数来执行。在Unity中,通过XLua等插件,开发者可以轻松地实现这一功能。XLua不仅支持函数替换,还支持构造函数、析构函数、属性、事件以及泛型类的替换,为开发者提供了极大的便利。

        本文将深入探讨Unity Hotfix技术在替换类中的函数方面的应用。


使用Hotfix

C#

using UnityEngine;

public class HotfixMain : MonoBehaviour
{
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");
        Debug.Log(Add1(110,4));
        Add2("长风破浪会有时,直挂云帆济沧海。");
    }

    void Update()
    {
        
    }

    public int Add1(int a,int b)
    {
        return 0;
    }

    public static void Add2(string str)
    {
        Debug.Log("烫烫烫烫烫烫烫烫烫烫烫烫烫烫");
    }
}

 Lua

Mian.lua

print('Lua脚本准备就绪')

--Unity中写lua执行
--xlua帮我们处理
--只要是执行1ua脚本 都会自动的进入我们的重定向函数中找文件

require("test")

test.lua

--Lua当中 热补丁代码固定写法
--xlua.hotfix(类,"函数名",lua函数)

xlua.hotfix(CS.HotfixMain,"Add1",function (self,a,b)
    return a+b;
end)

xlua.hotfix(CS.HotfixMain,"Add2",function (a)
    print(a)
end)

使用hotfix,必须做4个非常重要的操作

1.加特性

using UnityEngine;
using XLua;

[Hotfix]
public class HotfixMain : MonoBehaviour
{
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");
        Debug.Log(Add1(110,4));
        Add2("长风破浪会有时,直挂云帆济沧海。");
    }

    void Update()
    {
        
    }

    public int Add1(int a,int b)
    {
        return 0;
    }

    public static void Add2(string str)
    {
        Debug.Log("烫烫烫烫烫烫烫烫烫烫烫烫烫烫");
    }
}

2.加宏

Build Profiles/Project Settings/Scripting Define Symbol中添加HOTFIX_ENABLE


3.生成代码

XLua/Generate Code


4.hotfix注入

需要有和Assets同级别的Tools文件,XLua文件中复制过来

XLua/Hotfix Inject In Editor

提示成功

只要修改了热补丁类的代码,我们就要重新注入hotfix

实现效果

最后执行的是经过Lua热更新之后的代码逻辑


多函数替换

Lua

--Lua当中 热补丁代码固定写法
--xlua.hotfix(类,"函数名",lua函数)

xlua.hotfix(CS.HotfixMain,{
    Update = function (self)--使用成员函数需要传入自己为第一个参数
        print(os.time())--lua中的时间
    end,
    Add1 = function (self,a,b)
        return a+b;
    end,
    Add2 = function (a)--在C#中为静态函数,不需要传自己为第一个参数
        print(a)
    end
})

替换构造和析构函数 

C#

[Hotfix]
public class HotfixTest
{
    public HotfixTest()
    {
        Debug.Log("构造函数");
    }
    public void Speak(string str)
    {
        Debug.Log(str);
    }
    ~HotfixTest()
    {
        
    }
}

 Lua

与其他替换函数逻辑不同,Lua中构造和析构是先执行原逻辑,在执行Lua逻辑

xlua.hotfix(CS.HotfixTest,{
    --构造函数 热补丁 固定写法
    [".ctor"] = function ()
        print("Lua热补丁构造函数")
    end,
    Speak = function (self,a)
        print("这是计划的一部分"..a)
    end,
    --析构函数固定写法
    Finalize = function ()
        
    end
})

协程函数替换

整体规则和普通函数替换是一样的
区别在函数内部 是需要返回一个 xlua.util.cs_generator(函数)的返回值

C#

using System.Collections;
using UnityEngine;
using XLua;

[Hotfix]
public class HotfixMain : MonoBehaviour
{
    HotfixTest hotTest;
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");
        
        StartCoroutine(TestCoroutine());
    }

    void Update()
    {
        
    }

    IEnumerator TestCoroutine()
    {
        while(true)
        {
            yield return new WaitForSeconds(1);
            Debug.Log("C#协程打印一次");
        }
    }

    public int Add1(int a,int b)
    {
        return 0;
    }

    public static void Add2(string str)
    {
        Debug.Log("烫烫烫烫烫烫烫烫烫烫烫烫烫烫");
    }
}

util.lua位置

将文件复制一份改名xlua.util.lua到与自己写的lua文件同一级别的文件夹中

编写Lua脚本

--要在lua中配合C#协程函数,那么必须要使用它
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
})

索引器替换

C#

using System;
using System.Collections;
using UnityEngine;
using XLua;

[Hotfix]
public class HotfixMain : MonoBehaviour
{
    HotfixTest hotTest;
    public int[] array =new int[] {1,2,3};

    //属性
    public int Age
    {
        get
        {
            return 0;
        }

        set
        {
            Debug.Log(value);
        }
    }

    public int this[int index]
    {
        get
        {
            if(index>=array.Length || index < 0)
            {
                Debug.Log("索引不正确");
                return 0;
            }

            return array[index];
        }
        set
        {
            array[index] =value;
        }
    }

    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");

        this[99] = 100;
        Debug.Log(this[999]);
    }

    void Update()
    {
        
    }


}

Lua

xlua.hotfix(CS.HotfixMain,{
    --如果是属性进行热补丁重定向
    --set 属性名 是设置属性 的方法
    --get_属性名 是得到属性 的方法
    set_Age=function(self, v)
        print("Lua重定向的属性"..v)
    end,
    get_Age = function(self)
        return 10;
    end,
    --索引器固定写法
    --set_Item 设置索引器
    --get_Item 获取索引器
    set_Item = function (self,index,v)
        print("Lua重定向索引器,索引"..index.."值"..v)
    end,
    get_Item = function (self,index)
        print("Lua重定向")
        return 12
    end
})

事件替换

C#

using UnityEngine;
using UnityEngine.Events;
using XLua;

[Hotfix]
public class HotfixMain : MonoBehaviour
{
    event UnityAction myEvent;
    
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");

       myEvent +=TestTest;
       myEvent -=TestTest;
    }

    private void TestTest()
    {

    }

}

Lua

xlua.hotfix(CS.HotfixMain,{
    --add_事件名 代表事件加操作
    --remove_事件名 减操作
    add_myEvent = function (self,del)
        print(del)
        print("添加事件函数")
        --会去尝试使用1ua使用C#事件的方法去添加
        --在事件加减的重定向1ua函数中
        --千万不要把传入的委托往事件里存
        --否则会死循环
        --会把传入的 函数 存在1ua中
        --self:myEvent("+",de1)
    end,
    remove_myEvent = function (self,del)
        print(del)
        print("移除事件函数")
    end
})

注意:

如果要重定向事件加减到Lua中来
一定不要使用C#的事件加减了
self:myEvent("+/-",传入函数)
因为会造成死循环
如果想重定向,肯定是希望把逻辑让lua处理
所以一定是把传入的函数,存到lua里的容器中


泛型替换

替换规则和之前一样
区别是:类名后括号加泛型的类型,因为泛型时可变的,所以我们要指定某一个类型来进行替换
想替换几个类型,就写几个补丁

C#

[Hotfix]
public class HotfixTest2<T>
{
    public void Test(T str)
    {
        Debug.Log(str);
    }
}
using UnityEngine;
using XLua;

[Hotfix]
public class HotfixMain : MonoBehaviour
{
    
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");

        HotfixTest2<string> t1 =new HotfixTest2<string>();
        t1.Test("123");

        HotfixTest2<int> t2 =new HotfixTest2<int>();
        t2.Test(456);
    }

}

Lua

--泛型类 T是可以变化 那lua中应该如何替换呢 ?
--1ua中的替换 要一个类型一个类型的来

xlua.hotfix(CS.HotfixTest2(CS.System.String),{
    Test = function (self,str)
        print("lua中打的补丁"..str)
    end
})

xlua.hotfix(CS.HotfixTest2(CS.System.int32),{
    Test = function (self,str)
        print("lua中打的补丁"..str)
    end
})


网站公告

今日签到

点亮在社区的每一天
去签到