28.热补丁替换委托事件加减操作

28.xLua热补丁-事件加减操作替换


28.1 知识点

准备工作

创建有事件成员的测试类

[Hotfix]
public class Lesson28_Test : MonoBehaviour
{
    event UnityAction myEvent;

    private void TestFunction1()
    {
        Debug.Log("我是C#中的函数TestFunction1");
    }

    private void TestFunction2()
    {
        Debug.Log("我是C#中的函数TestFunction2");
    }

    private void Start()
    {
        myEvent += TestFunction1;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            myEvent += TestFunction1;
        }

        if (Input.GetKeyDown(KeyCode.W))
        {
            myEvent -= TestFunction1;
        }

        if (Input.GetKeyDown(KeyCode.E))
        {
            myEvent += TestFunction2;
        }

        if (Input.GetKeyDown(KeyCode.R))
        {
            myEvent -= TestFunction2;
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log($"myEvent是不是空 {myEvent == null}");
            //myEvent是不是空 True
            //因为是把函数加到lua中处理了,没有加到myEvent中,所以myEvent一直是空

            Action InvokeMyEvent = LuaManager.Instance.Global.Get<Action>("InvokeMyEvent");
            InvokeMyEvent();
        }
    }
}

启动Lua脚本

LuaManager.Instance.Init();
LuaManager.Instance.DoLuaFile("Lesson28_xLua热补丁_事件加减操作替换");

Lesson28_Test test = this.gameObject.AddComponent<Lesson28_Test>();

事件加减操作替换

事件加减操作替换:当 C# 对事件做 += / -= 时,若做了 add_事件名 / remove_事件名 热补丁,实际不会改 C# 里事件字段,而是把 要增删的委托 交给 Lua 补丁逻辑处理(正文用表缓存委托再在 Lua 侧统一触发)。

-- 创建一个表来存储事件处理函数,会把C#对某个事件添加的函数添加到这个表中
local eventHandlers = {}

-- 事件加减操作热补丁替换 操作_事件名 把对事件的操作当成一个成员函数 会有一个委托变量作为参数
xlua.hotfix(CS.Lesson28_Test, {

    -- add_事件名
    add_myEvent = function(self, delegate)
        print(delegate)
        print("添加事件函数")

        -- 将委托存储到表中
        table.insert(eventHandlers, delegate)

        -- 在事件加减操作重定向函数中不要把传入的委托往事件里存,以避免死循环
        -- self:myEvent("+", delegate)--死循环
    end,

    -- remove_事件名 减操作
    remove_myEvent = function(self, delegate)
        print(delegate)
        print("移除事件函数")

        -- 在移除事件时从表中移除委托
        for i, handler in ipairs(eventHandlers) do
            -- 不能直接==判断 要比较地址
            if  tostring(handler) == tostring(delegate) then
                table.remove(eventHandlers, i)
                break
            end
        end
    end

})

-- 触发所有C#加进来的函数
function InvokeMyEvent()
    for i, handler in ipairs(eventHandlers) do
        handler()
    end
end

测试结果

按下Q和E可以给委托添加函数,WR移除,空格触发。但是是在Lua遍历函数表触发的,C#的委托变量始终为空


28.2 知识点代码

Lesson28_xLua热补丁_事件加减操作替换.lua

print('我是Lua脚本 Lesson28_xLua热补丁_事件加减操作替换')

print("*********知识点一 事件加减操作替换***********")

-- 创建一个表来存储事件处理函数,会把C#对某个事件添加的函数添加到这个表中
local eventHandlers = {}

-- 事件加减操作热补丁替换 操作_事件名 把对事件的操作当成一个成员函数 会有一个委托变量作为参数
xlua.hotfix(CS.Lesson28_Test, {

    -- add_事件名
    add_myEvent = function(self, delegate)
        print(delegate)
        print("添加事件函数")

        -- 将委托存储到表中
        table.insert(eventHandlers, delegate)

        -- 在事件加减操作重定向函数中不要把传入的委托往事件里存,以避免死循环
        -- self:myEvent("+", delegate)--死循环
    end,

    -- remove_事件名 减操作
    remove_myEvent = function(self, delegate)
        print(delegate)
        print("移除事件函数")

        -- 在移除事件时从表中移除委托
        for i, handler in ipairs(eventHandlers) do
            -- 不能直接==判断 要比较地址
            if  tostring(handler) == tostring(delegate) then
                table.remove(eventHandlers, i)
                break
            end
        end
    end

})

-- 触发所有C#加进来的函数
function InvokeMyEvent()
    for i, handler in ipairs(eventHandlers) do
        handler()
    end
end

Lesson28_xLua热补丁_事件加减操作替换

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

public class Lesson28_xLua热补丁_事件加减操作替换 : MonoBehaviour
{
    void Start()
    {
        LuaManager.Instance.Init();
        LuaManager.Instance.DoLuaFile("Lesson28_xLua热补丁_事件加减操作替换");

        Lesson28_Test test = this.gameObject.AddComponent<Lesson28_Test>();
    }
}

[Hotfix]
public class Lesson28_Test : MonoBehaviour
{
    event UnityAction myEvent;

    private void TestFunction1()
    {
        Debug.Log("我是C#中的函数TestFunction1");
    }

    private void TestFunction2()
    {
        Debug.Log("我是C#中的函数TestFunction2");
    }

    private void Start()
    {
        myEvent += TestFunction1;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            myEvent += TestFunction1;
        }

        if (Input.GetKeyDown(KeyCode.W))
        {
            myEvent -= TestFunction1;
        }

        if (Input.GetKeyDown(KeyCode.E))
        {
            myEvent += TestFunction2;
        }

        if (Input.GetKeyDown(KeyCode.R))
        {
            myEvent -= TestFunction2;
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log($"myEvent是不是空 {myEvent == null}");
            //myEvent是不是空 True
            //因为是把函数加到lua中处理了,没有加到myEvent中,所以myEvent一直是空

            Action InvokeMyEvent = LuaManager.Instance.Global.Get<Action>("InvokeMyEvent");
            InvokeMyEvent();
        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏