一.热补丁简介

  热补丁主要是用于将纯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
})

    

热更新应用--热补丁Hotfix学习笔记的更多相关文章

  1. 【Quick 3.3】资源脚本加密及热更新(三)热更新模块

    [Quick 3.3]资源脚本加密及热更新(三)热更新模块 注:本文基于Quick-cocos2dx-3.3版本编写 一.介绍 lua相对于c++开发的优点之一是代码可以在运行的时候才加载,基于此我们 ...

  2. webpack实现“热更新”和“热加载”(webpack3.6新增)

    之前的博文有提到怎么样去实现热更新,但是居然要用到另外一个node框架(express)而且新增了一个入口(entry)两个插件(plugin)来实现,大大提高了配置的复杂度,这样其实对使用webpa ...

  3. webpack+express实现“热更新”和“热加载”(webpack3.6以前的做法)

    “热更新”:对应的是 'webpack-dev-middleware' 中间件 “热加载”:对应的是 'webpack-hot-middleware' 中间件 为了使用这两个中间件,必须修改“webp ...

  4. 关于iOS 热更新(热修复)你必须知道的一种方法- JSPatch

    本文为转载文章 . 版权归原文所有. 原文链接:iOS 5分钟集成热修复(JSPatch) 前言 在iOS中有很多种热修复方案,在这里我就不一一介绍了 这里有一篇介绍热修复的文章:iOS中的HotFi ...

  5. 使用diff制作补丁【学习笔记】

    源文件:main.c #include <stdio.h> int main() { printf("hello"); } 修改之后的文件: main1.c #incl ...

  6. RN学习1——前奏,app插件化和热更新的探索

    react_native_banner-min.png React Native(以下简称RN)有大量前端开发者的追捧.前端开发是一个活跃的社区,一直尝试着一统前后端,做一个全栈开发,RN就是他们在客 ...

  7. 另类Unity热更新大法:代码注入式补丁热更新

    对老项目进行热更新 项目用纯C#开发的? 眼看Unity引擎热火朝天,无数程序猿加入到了Unity开发的大本营. 一些老项目,在当时ulua/slua还不如今天那样的成熟,因此他们选择了全c#开发:也 ...

  8. 热更新(一) 之Lua语法的学习

    热更新 如热更新果需要更换UI显示,或者修改游戏的逻辑,这个时候,如果不使用热更新,就需要重新打包,然后让玩家重新下载(浪费流量和时间,体验不好).热更新可以在不重新下载客户端的情况下,更新游戏的内容 ...

  9. 移动端热更新方案(iOS+Android)

    PPT资源包含iOS+Android 各种方案分析:https://github.com/qiyer/Share/blob/master/%E7%83%AD%E6%9B%B4%E6%96%B0%E5% ...

随机推荐

  1. 如何在 macOS 上进行滚动截屏

    如何在 macOS 上进行滚动截屏 Shift-Command-5 https://support.apple.com/zh-cn/guide/mac-help/mh26782/mac demo Xn ...

  2. 2019 front-end job Interview

    2019 front-end job Interview 2019 前端面试题 掘金 https://juejin.im/tag/面试 https://juejin.im/post/5c875791e ...

  3. eui & search select

    eui & search select https://element.eleme.io/#/zh-CN/component/select demo <template> < ...

  4. svg & stroke & style & class

    svg & stroke & style & class svg selected style methods style class, !important fill, st ...

  5. vue常用方法封装-一键安装使用(赠送免费工具)

    相信大家在使用vue开发过程中一定遇到了各种方法的整理收集,每次遇到新的问题都需要找到合适的方法 这里我给大家封装了一些vue项目中常用到的方法合集,免费提供费大家 因此,jsoften横空出世,不为 ...

  6. 我眼中的价值币——NGK(下)

    跨链交互方案并不是区块链世界中的一个新课题.自比特币诞生揭开智能合约的序幕之后,跨链交互的需求便产生了.但是,经过十年的发展,市场中的跨链解决方案进展缓慢,究之原因有以下几个方面. 首先,区块链的去中 ...

  7. ffmpeg中的日志控制、保存日志到指定文件、处理进度查询

    ffmpeg默认就会输出一些日志,包含编译的工具(gcc版本).可用的组件(--enable-xxxx).组件版本号码,如下图 这些信息是默认输出的,每次执行合作都会打印在控制台中,如果不想看这些信息 ...

  8. [转]Ubuntu16.04安装搜狗输入法

    原文地址:https://blog.csdn.net/u013894834/article/details/60357071,转载主要方便随时查阅,如有版权要求,请及时联系. 1.首先我们先去搜狗输入 ...

  9. IntelliJ IDEA 还能画思维导图,果然最强 IDE!

    最近栈长发现 IntelliJ IDEA 居然还能画思维导图,太牛逼了! 当然这得借助 IDEA 的 UML 插件,因为它本身也是一个 UML 图,所以这篇就从 UML 图开撕,看 IDEA 怎么画思 ...

  10. 模拟web服务器 (小项目) 搭建+部署

    模拟web服务器:可以从浏览器中访问到自己编写的服务器中的资源,将其资源显示在浏览器中. 技术选型: corejava 线程池 同任务并发执行 IO流 传递数据 客户端也会像服务端发送数据, 服务器像 ...