xLua(九)——实战

article/2025/9/28 2:38:50

一:使用xLua的步骤

——导入xLua插件
其实xLua本质就是一个Unity工程,把Asset中的文件导入到Unity工程中就搞定了(导入之后编辑器菜单栏会扩展出一个XLua选项)

 


——添加宏
File——Build Settings——Player Settings——Other Settings——Scriptsing Define Symbols——输入HOTFIX_ENABLE——按下Enter
检测添加是否成功:选择之前菜单栏的XLua选项,发现多出了一个Hotfix Inject In Editor选项

 


——重新生成代码&重新注入代码

每当CS代码发生修改时,就必须点击重新生成代码(生成成功后控制台输出:finished! use XXX ms)
和将热修复补丁注入到Unity编辑器中(注入成功后控制台输出:XXX had injected!)

如果点击Hotfix Inject In Editor时报错:please install the Tools
则需要将xLua插件中的Tools文件夹也导入Unity工程中(注意与Assets文件夹同级)


二:xLua的一些坑

——没有导入Tools文件夹
如果报以下错误:please install the Tools
则需要将xLua插件中的Tools文件夹也导入Unity工程中(注意与Assets文件夹同级)


——Untiy工程目录不能带有中文
如果报以下错误:Exception: project path must contain only ascii character
则需要将项目放在一个没有中文的目录下


——没有重新生成代码&重新注入代码&没有添加热修复标签
如果报以下错误:LuaException: xlua.access, no field __Hotfix0_XXX
一种情况是没有重新生成代码并重新注入代码到Unity编辑器中

或者是没有给XXX类添加[Hotfix]的标签


——C#仍指向Lua虚拟机中某个function的委托
如果报以下错误:InvalidOperationException: try to dispose a LuaEnv with C# callback!
则需要使用xlua.hotfix(class, method, nil)删除(注入的时候是使用xlua.hotfix(class, method, func)注入的)

建议开发过程中单独写一个Lua脚本进行所有委托的销毁,将加载此脚本的方法写在释放Lua虚拟机的前面

大概说一下热补丁的实现原理,当我们给一个类打补丁后使用xlua.hotfix为类中的方法重写时,这个重写的Lua方法会注册到Lua虚拟机的一个委托中,当我们释放Lua虚拟机时,这个Lua方法并没有被释放所以会报错
关于热补丁的实现原理,推荐知乎上xLua作者写的:xLua热补丁实现原理
另外推荐一篇介绍中间语言IL的文章:中间语言IL


——访问成员方法时参数中没有传入调用者自身
如果报以下错误:LuaException: invalid arguments to XXX!
则说明XXX方法是一个成员方法,参数中需要传入调用者自身
例如SetParent方法是一个成员方法,可以使用冒号去访问或者在参数中传入调用者自身


——打上[LuaCallCSharp]或者[LuaCallCSharp]标签


——报一些奇怪的错误
删除Example文件夹,清空代码重新生成注入


三:打补丁的开发过程

——正常开发C#代码
——在所有可能出现问题的类上打上[Hotfix]标签(不能后期发布后再打标签)
——在所有Lua调用C#的方法上打上[LuaCallCSharp]标签,在所有C#调用Lua的方法上打上[CSharpCallLua]标签
——修改bug时只需要修改Lua文件,修改资源时只需要更新ab包,用户只需要去下载Lua文件和ab包即可


四:不同情况下补丁脚本的重写

——对于CS脚本中的大多数方法
例如在CS脚本中:

对应的Lua补丁脚本是这样的:

xlua.private_accessible(CS.Text)    --这样才可以使用类中的私有字段,属性,方法xlua.hotfix(CS.Text,'Method',function(self,value)value=self.x	local _go=CS.UnityEngine.Object.Instantiate(self.prefabGo,self.UnityEngine.Vector3(value,0,0),CS.UnityEngine.Quaternion.identity)_go.transform:SetParent(CS.UnityEngine.GameObject.Find("Canvas").transform);
end)

 

 


——对于CS脚本中需要修改的地方在补丁脚本中执行,不需要修改的地方仍然在CS脚本中执行(这种方式尽量少使用,会降低性能)
例如在CS脚本中:

对应的Lua补丁脚本中我们希望go=GameObject.Find("MyGo").gameObject这句话仍然在CS脚本中执行,补丁脚本中只修改value的值:

local util=require 'util'xlua.private_accessible(CS.Test) 
util.hotfix_ex(CS.Test,'Method',function(self)self:Method()self.value=5
end)

util是xLua提供的一个库,因为require的加载是加载同级目录的脚本,所以需要将util.lua.txt复制到补丁脚本的同级目录下
util.lua.txt的位置在xLua-master\Assets\XLua\Resources\xlua中

 

 

——对于CS脚本中的Start生命周期函数
有些时候我们为CS脚本的方法打补丁时,会发现补丁代码重写的方法并没有执行,仍然执行的是CS中的原方法,这是因为加载Lua脚本的代码(也就是补丁代码)没有最先被调用,而是在CS原方法执行后再被调用,这样的话补丁方法就失去了作用
例如将加载Lua补丁脚本的代码放在Start方法中,补丁代码重写的也是一个类中的Start方法,这样就有可能先执行CS原方法,补丁方法就失去了作用,简单工程中建议加载Lua补丁脚本的代码放在Awake中,加载Lua脚本的代码最好放在最最最最最前!

 


——对于CS脚本中的Random.Range
首先转到Random.Range的定义,可以看出它是一个重载方法

接下来在CS脚本和Lua补丁脚本中测试,运行后可以得出xLua默认调用的是返回值为float的Random.Range方法,又因为CS访问Lua文件中的number类型时,会进行自动的类型转换(低类型可以自动转高类型,也就是可以给高类型的值赋予一个低类型的值)因为Lua中的数字类型统一为number,而C#有int,double,float等类型,例如用Lua文件中定义的一个本质为float类型的值去赋值给C#中的int类型的变量,则会输出为0),以上的测试结果也是如此,因为之前CS脚本中定义的num是一个int类型数字,而UnityEngine.Random.Range得到的是一个float类型数字,所以num会赋值为0

1.第一种解决方法:使用Unity中的向下取整函数将小数变为整数

xlua.hotfix(CS.Test,'Start',function(self)self.num=CS.UnityEngine.Mathf.FloorToInt(CS.UnityEngine.Random.Range(0,5))
end)

 

 

——对于CS脚本中的泛型方法
例如在CS脚本中:

对应的Lua补丁脚本是这样的:

xlua.hotfix(CS.Test,'Start',function(self)local _go=CS.UnityEngine.Object.Instantiate(self.go)_go:GetComponent('Rigibody').useGravity=false
end)

 

 

——补丁脚本中加载AB包资源(例如加载一个游戏物体)
首先前期在CS中写好扩展的接口,提供后期有需要的时候去调用:

using UnityEngine;
using System.Collections.Generic;public class Extension
{private static Dictionary<string, GameObject> prefabDict;//加载资源public static void LoadResource(string abName, string resName){AssetBundle ab = AssetBundle.LoadFromFile(@"Assets/MyAssetBundles/" + abName);GameObject _go = ab.LoadAsset<GameObject>(resName);if (prefabDict == null){prefabDict = new Dictionary<string, GameObject>();}prefabDict.Add(resName, _go);}//得到物体public static GameObject GetGo(string resName){return prefabDict[resName];}
}

之后在Lua补丁脚本中实例化这个物体

--在Start或者Awake中先加载出这个资源
CS.Extension.LoadResource('abName','resName')--当需要的时候再实例化出来
local _go=CS.Extension.GetGo('resName')
CS.UnityEngine.Object.Instantiate(_go)

 

 

——对于无法预测的CS类(无法预测的功能)
例如当前有一个物体,我们无法预测它后期会添加什么功能,我们可以给它添加一个空类,空类里定义一些可能会用到的空方法:

using UnityEngine;
using XLua;[Hotfix]
public class Empty : MonoBehaviour
{private void Start(){}private void Update(){}private void Method1(){}private void Method2(){}
}

之后需要的时候在Lua补丁脚本中重写打了补丁的空类中提供的方法:

xlua.private_accessible(CS.Empty)
xlua.hotfix(CS.Empty,'Start',function(self)end)
xlua.hotfix(CS.Empty,'Update',function(self)	end)
xlua.hotfix(CS.Empty,'Method1',function(self)end)

 

 

——对于CS中的协程
例如在CS脚本中:

对应的Lua补丁脚本是这样的:

local util=require 'util'xlua.hotfix(CS.Test,{
Start=function(self)return util.cs_generator(function()coroutine.yield(CS.UnityEngine.WaitForSeconds(5))	CS.UnityEngine.MonoBehaviour.print('Wait For 5 Seconds')end)end
})

 


http://chatgpt.dhexx.cn/article/mWYLvP92.shtml

相关文章

【XLua】简单使用

文章目录 前言1 配置1.1 配置宏1.2 XLua配置 2 lua和C#相互调用2.1 XLua.CSharpCallLua2.2 XLua.LuaCallCSharp 3 加载器 前言 XLua本质上是为Unity提供了使用lua的能力&#xff0c;实际多用于热更新。 热更新&#xff0c;因为要给代码打标签才能生效&#xff0c;所以需要预测…

xLua介绍

xLua地址&#xff1a;传送门 Xlua是啥&#xff1f; 2016年 腾讯推出的 一种 unity下 lua 编成的解决方案 基本概念介绍&#xff1a; 1.模块 模块就是一个 程序库&#xff0c;可以通过 require 加载&#xff0c;得到了一个表示 table的全局变量 这个table 就像一个命名空间&am…

Lua快速入门篇(XLua教程)(Yanlz+热更新+xLua+配置+热补丁+第三方库+API+二次开发+常见问题+示例参考)

《Lua热更新》 ##《Lua热更新》发布说明&#xff1a; “Lua热更新”开始了&#xff0c;立钻哥哥终于开始此部分的探索了。 作为游戏发布迭代的重要技术&#xff1a;Lua热更新在网络游戏迭代更新中非常重要&#xff0c;特别是对于AppStore这样的平台&#xff0c;我们只需要定…

XLua加载

XLua加载lua文件的方式 LuaEnv.DoString(print("hello world")); //直接执行lua的语句&#xff0c;在函数体内的语句格式要符合lua的语法 LuaEnv.DoString("require byfile")//使用require lua文件名也可在unity中加载lua 但是在unity中需要把文件放置在…

XLua系列讲解_Helloworld

一、XLua简介 XLua是Unity3D下Lua编程解决方案&#xff0c;自2016年初推广以来&#xff0c;已经应用于十多款腾讯自研游戏&#xff0c;因其良好性能、易用性、扩展性而广受好评。现在&#xff0c;腾讯已经将xLua开源到GitHub。 二、Xlua的优点 简洁易用&#xff0c;容易上手可…

Unity XLua Hotfix热更新配置笔记

Unity XLUA Hotfix热更新配置笔记 目录 Unity XLUA Hotfix热更新配置笔记 配置热更新步骤&#xff1a; 下载XLUA下载压缩包解压 复制xlua 和plugins到assets开启热补丁特性 先添加宏 HOTFIX_ENABLE;INJECT_WITHOUT_TOOL报“This delegate/interface must add to CSharpCallLu…

xLua热更新(一)xLua基本使用

一、什么是xLua xLua为Unity、 .Net、 Mono等C#环境增加Lua脚本编程的能力&#xff0c;借助xLua&#xff0c;这些Lua代码可以方便的和C#相互调用。 xLua是用来实现Lua代码与C#代码相互调用的插件。我们可以借助这个插件来实现热更新方案。 那么为什么要选择Lua实现热更新呢&am…

Bug-CTF-秋名山老司机(正则匹配)

题目: 没有啥思路&#xff0c;意外地刷新了一下页面&#xff0c;发现数值变化了 再刷新一次试试&#xff0c;出来一个提示&#xff0c;大概意思是需要提交结果&#xff0c;这里也不知道该怎么传参&#xff0c;也不晓得怎么写这个脚本&#xff0c;只能参考其他大佬的思路了 解题…

BUGKU------秋名山老司机

看到这个就直接上python吧&#xff0c;用eval计算子式 import requests from bs4 import BeautifulSoup r requests.session() s r.get(http://123.206.87.240:8002/qiumingshan/) soup BeautifulSoup(s.text, "html.parser") a soup.find(div) d {"valu…

bugku秋名山车神

不断的刷新&#xff0c;发现表达式一直在变换&#xff0c;这种必须写脚本&#xff0c;才能跟上速度。直接上代码 import re import requests srequests.session() rs.get("http://123.206.87.240:8002/qiumingshan/") searchObj re.search(r^<div>(.*)\?;<…

【BugkuCTF】Web--秋名山老司机

Description: http://123.206.87.240:8002/qiumingshan/ 是不是老司机试试就知道。 Solution: 打开网页 2秒解决问题真是稳稳的写脚本……但是不知道提交啥&#xff0c;刷新网页看看提示让用POST方式传递一个value变量&#xff0c;构造脚本 import requests import re url htt…

CTF-web-秋名山老司机

前言&#xff1a;小编也是现学现卖&#xff0c;方便自己记忆&#xff0c;写的不好的地方还请包涵&#xff0c;也欢迎各位大佬多多批评指正。 网址&#xff1a;秋名山老司机 1.打开网址&#xff0c;提示需要两秒内计算出数值&#xff0c;手工几乎不可能实现。 2.思路:利用pyt…

秋名山车神

解题思路&#xff1a;看到这种题要在两秒类算出&#xff0c;人工肯定不可能&#xff0c;直接上脚本&#xff0c;由于我不会写python 脚本&#xff0c;直接在网上找了一篇大佬的脚本 import requests #安装requests库 import re url http://114.67.246.176:16847 #改为自己题…

爬虫笔记-Bugku秋名山老司机(入门)

记一次python爬虫笔记 题目&#xff1a;bugku-秋名山老司机 题目要求&#xff1a;两秒内提交一道很长的计算题答案&#xff0c;并且式子每次刷新都会变动 如&#xff1a; 多刷新几次可见题目提示&#xff0c;需要用post传入值&#xff0c;变量名为value 创建py文件&#xf…

ctf靶场-bugku-秋名山老司机,速度要快

页面快速计算(秋名山老司机) 1.靶场网址 http://123.206.87.240:8002/qiumingshan/ 2.脚本实现 import requests import re url"http://123.206.87.240:8002/qiumingshan/" srequests.Session() #储存session rs.get(url) #用此身份执行get请求 searchobjre.sea…

[bugku]-秋名山车神详解

解题 每一次刷新都不一样 post传参value 脚本1 import requests import re url http://114.67.175.224:10053/ s requests.Session() source s.get(url) expression re.search(r(\d[\-*])(\d), source.text).group() result eval(expression) post {value: result} prin…

Bugku_Web18_秋名山车神

1.查看源码 <head> <title>下面的表达式的值是秋名山的车速</title> <meta charset"UTF-8"> </head> <p>亲请在2s内计算老司机的车速是多少</p> <div>373719747-1878154638-1233431774-1476346255*1056350133121800…

bugku 秋名山车神

get新知识&#xff1a;一些有关python爬虫的基本知识 解题部分 题目中都是这样的大数字进行计算&#xff0c;并且需要短时间内计算&#xff0c;所以这不得不使用脚本进行解题&#xff0c;脚本如下 #bugku 秋名山车神 --爬虫练习 import requests import re ​ srequests.Sess…

web——秋名山老司机(100)——Bugku

000 靶场链接 http://123.206.87.240:8002/web16/ 001 题目描述 002 解题过程 一看大数运算就觉得要用python&#xff0c;然后就只能找wp看看 多刷新几次会有提示出来 一个value post 创建步骤 先建立文本文档&#xff0c;后缀改为.py&#xff0c;然后右键使用IDE打开 代…

求秋名山老司机车速

http://120.24.86.145:8002/qiumingshan/ 两秒内算出秋名山车神的车速。感觉很吊的。 刚开始知道的大概的知道就是算出答案&#xff0c;但是怎么提交&#xff0c;后来多刷新几次发现。 给我post value。好吧&#xff0c;翻译也翻译的很蛋疼。反正就是需要value这个作为提交的参…