[Xlua] Hotfix

阅前须知

本文热重载的C#脚本为:

using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using XLua;
[Hotfix]
public class HotFixMain : MonoBehaviour
{
    public HotfixCsharp hotfixCsharp;
    private int[] array = { 1, 2, 3 };
    public int Age
    {
        get { return 0; }
        set
        {
            Debug.Log(value);
        }
    }

    public int this[int index]
    {
        get
        {
            if (index > array.Length)
            {
                Debug.Log("index out of array length");
                return 0;
            }

            return array[index];
        }
        set
        {
            if (index > array.Length)
            {
                Debug.Log("index out of array length");
                return;
            }
            array[index] = value;
        }
    }
    event UnityAction myEvent;
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Hotfix_Main");
        Debug.Log(Add(1, 0));
        Speak("ColdPlay");
        //Learn2_MutiFunc
        hotfixCsharp = new HotfixCsharp();
        hotfixCsharp.Speak("HotPlay");
        //Learn3_Coroutine
        StartCoroutine(TestCoroutine());
        //Learn4_IndexerAndProperty
        Age = 100;
        Debug.Log($"Age {this.Age}");
        Debug.Log($"indexer {this[99]}");
        this[999] = 1;
        //Learn5_Event
        myEvent += TestHandle;
        myEvent -= TestHandle;
        //Learn6_Generic
        HotfixTestGeneric<string> t1 = new HotfixTestGeneric<string>();
        t1.Test("hotfix generic");
        HotfixTestGeneric<int> t2 = new HotfixTestGeneric<int>();
        t2.Test(1000);
        


    }
    void Update()
    {

    }
    public int Add(int a, int b)
    {
        return 0;
    }
    public static void Speak(string str)
    {
        Debug.Log("Speak");
    }
    IEnumerator TestCoroutine()
    {
        int i = 0;
        while (true)
        {
            yield return new WaitForSeconds(1);
            i++;
            Debug.Log("csharp coroutine "+i);
            if (i == 10)
                break;
        }
    }
    public void TestHandle()
    {

    }
}
[Hotfix]
public class HotfixCsharp
{
    public HotfixCsharp()
    {
        Debug.Log("HotfixCsharp Constructor");
    }
    public void Speak(string str)
    {
        Debug.Log(str);
    }
    ~HotfixCsharp()
    {

    }
}
[Hotfix]
public class HotfixTestGeneric<T>
{
    public void Test(T str)
    {
        Debug.Log(str);
    }
}

Hotfix

  • Xlua热重载一个C#方法
-- Xlua.hotfix(类,"函数名",lua函数)

热重载要做的准备

  1. 打开Unity Project Settings->Player->Other Settings 添加 HOTFIX_ENABLE

image

  1. 对于要热重载的类需要加上[Hotfix]特性
  2. GenerateCode

image

  1. Hotfix Inject

image

要注意每次我们修改了要Hotfix的C#类都记得要重复3、4步

热重载相关

image

多函数替换

  • 表的索引为方法名、成员方法要加self,参数数量要一致(lua弱类型)
  • 注意构造函数和析构函数的固定写法
  • 构造函数和析构函数不是完全替换,是先执行c#的逻辑再执行lua的逻辑
print("************多函数替换************")
-- xlua.hotfix(类,表)
xlua.hotfix(CS.HotFixMain,
    {
        Update = function(self)
            print(os.time())
        end,
        Add = function(self, a, b)
            return a + b
        end,
        Speak = function(str)
            print(str)
        end
    })
xlua.hotfix(CS.HotfixCsharp,
{
    --构造函数固定写法
    [".ctor"]=function()
        print("lua constructor")
    end,
    Speak=function(self,str)
        print("lua speak " .. str)
        
    end,
    --析构函数固定写法
    Finalize=function()
        
    end
})

携程替换

image

  • 需要使用一个lua function 然后return util.cs_generator()转换后的携程
  • hofix(table):

    • :C# 方法名(如 TestCoroutine​)。
    • :必须是一个 Lua 函数(即使你只是单纯想返回一个 IEnumerator​)。
print("************携程替换************")
util=require("xlua.util")
xlua.hotfix(CS.HotFixMain, {
    TestCoroutine = function(self)
        return util.cs_generator(function()
            local i = 0
            while i < 10 do  -- 条件控制:i >= 10 时退出循环
                coroutine.yield(CS.UnityEngine.WaitForSeconds(1))
                i = i + 1
                print("Lua Coroutine,i =", i)
            end
            print("携程已自动停止")
        end)
    end
})

索引器和属性替换

image

固定写法

  • set_属性名:设置属性
  • get_属性名:获取属性
  • set_Item:使用索引器设置
  • get_Item:使用索引器获取
print("************替换索引器和属性************")
xlua.hotfix(CS.HotFixMain,{
    --属性
    --set_属性名:设置属性
    --get_属性名:获取属性
    set_Age=function(self,v)
        print("lua property v:" .. v)        
    end,
    get_Age=function (self)
        return 10
    end,
    --索引器固定写法
    --set_Item:设置
    --get_Item:获取
    set_Item=function(self,i,v)
        print("lua indexer" .. i .. " ".. v )
    end,
    get_Item=function(self,i)
        print("lua get indexer" .. i)
        return 199
    end
})

Event的+和-的替换

image

用于统一事件的管理或者阻止一些绑定

固定写法

  • add_事件名:event+=
  • remove_事件名 event-=
print("************替换事件+- ************")
xlua.hotfix(CS.HotFixMain,{
    --add_事件名:event+=
    --remove_事件名 event-=
    add_myEvent=function(self,del)
        print(del)
        print("add event func")
        -- self:myEvent("+",del) 会造成死循环!!!
        -- 一般声明一个容器,存在容器中 

    end,
    remove_myEvent=function(self,del)
        print(del)
        print("remove event func")
    end
})

输出

image

替换泛型类

image

  • CS.HotfixTestGeneric(CS.System.String)传入对应的类型
print("************替换泛型类 ************")
--lua中需要分别替换 即分别替换T为string、int....的类

xlua.hotfix(CS.HotfixTestGeneric(CS.System.String),{
    Test=function(self,str)
        print("lua generic " .. str)
    end
})
xlua.hotfix(CS.HotfixTestGeneric(CS.System.Int32),{
    Test=function(self,int)
        print("lua generic " .. int)
    end
})

完整输出

image

总结

本文介绍了如何在Unity中使用XLua进行热重载(Hotfix)功能。主要内容包括:热重载前的准备工作(如添加宏定义、添加Hotfix特性、生成代码和注入)、热重载的基本语法(xlua.hotfix),以及通过示例代码演示了如何重载普通方法、静态方法、构造函数、析构函数、协程、索引器、属性、事件和泛型类方法等不同场景。文章提供了详细的C#脚本示例和对应的Lua热重载代码,涵盖了热重载的各种常见应用场景。

最后修改:2025 年 07 月 07 日
如果觉得我的文章对你有用,请随意赞赏