更新Xlua 到最新版本
This commit is contained in:
Assets
Plugins
Android.metaWSA.meta
XLua.metaAndroid
libs
IOS
Script
AssetUpdate
WSA
WebGL.metaWebGL
arm64.metaarm64
x86.metaXLua
CHANGELOG.txtCHANGELOG.txt.meta
Doc
Configure_EN.mdHotfix_EN.md
Editor.metaMaterials
XLua_API.mdXLua教程.mdcompatible_bytecode.mdconfigure.mdcustom_generate.mdfaq.mdfeatures.mdhotfix.mdlogo.png.metaxLua.pngxLua.png.metaEditor
ExampleConfig.csExampleConfig.cs.metaXLuaGenConfig.csXLuaUnityDefaultConfig.csXLuaUnityDefaultConfig.cs.meta
Gen.metaGen
DelegatesGensBridge.csDelegatesGensBridge.cs.metaEnumWrap.csEnumWrap.cs.metaIMarketingActRetDelBridge.cs.metaLuaMainWrap.cs.metaLuaUIBehaviourWrap.cs.metaPackUnpack.cs.metaSdkControlWrap.csSdkControlWrap.cs.metaSystem_Collections_Generic_List_1_System_Int32_Wrap.cs.metaSystem_Collections_HashtableWrap.cs.metaSystem_Collections_IEnumerableBridge.cs.metaSystem_Collections_IEnumeratorBridge.cs.metaSystem_ObjectWrap.cs.metaTableManagerLuaWrap.cs.metaTutorial_BaseClassWrap.csTutorial_BaseClassWrap.cs.metaTutorial_CSCallLua_ItfDBridge.csTutorial_CSCallLua_ItfDBridge.cs.metaTutorial_DerivedClassExtensionsWrap.csTutorial_DerivedClassExtensionsWrap.cs.metaTutorial_DerivedClassWrap.csTutorial_DerivedClassWrap.cs.metaTutorial_ICalcWrap.csTutorial_ICalcWrap.cs.metaUnityEngine_AnimationClipWrap.cs.metaUnityEngine_AnimationCurveWrap.cs.metaUnityEngine_BehaviourWrap.cs.metaUnityEngine_BoundsWrap.cs.metaUnityEngine_ColorWrap.cs.metaUnityEngine_ComponentWrap.cs.metaUnityEngine_DebugWrap.cs.metaUnityEngine_GameObjectWrap.cs.metaUnityEngine_KeyframeWrap.cs.metaUnityEngine_LightWrap.cs.metaUnityEngine_MathfWrap.cs.metaUnityEngine_MonoBehaviourWrap.cs.metaUnityEngine_ObjectWrap.cs.metaUnityEngine_ParticleSystemWrap.cs.metaUnityEngine_QuaternionWrap.cs.metaUnityEngine_Ray2DWrap.cs.metaUnityEngine_RayWrap.cs.metaUnityEngine_RendererWrap.cs.metaUnityEngine_ResourcesWrap.cs.metaUnityEngine_SkinnedMeshRendererWrap.cs.metaUnityEngine_TextAssetWrap.cs.metaUnityEngine_TimeWrap.cs.metaUnityEngine_TransformWrap.cs.metaUnityEngine_Vector2Wrap.cs.metaUnityEngine_Vector3Wrap.cs.metaUnityEngine_Vector4Wrap.cs.metaUnityEngine_WWWWrap.cs.metaWrapPusher.csWrapPusher.cs.metaXLuaGenAutoRegister.csXLuaGenAutoRegister.cs.metalink.xmllink.xml.meta
Resources
Src.metaSrc
CodeEmit.csCodeEmit.cs.metaCopyByValue.csCopyByValue.cs.metaDelegateBridge.csDelegateBridge.cs.metaEditor.meta
Tutorial.metaEditor
Generator.csGenerator.cs.metaHotfix.csHotfix.cs.metaLinkXmlGen.meta
GenAttributes.csGenAttributes.cs.metaGenericDelegateBridge.csGenericDelegateBridge.cs.metaInternalGlobals.csInternalGlobals.cs.metaLuaBase.csLuaBase.cs.metaLuaDLL.csLuaDLL.cs.metaLuaEnv.csLuaEnv.cs.metaLuaException.csLuaException.cs.metaLuaFunction.csLuaFunction.cs.metaLuaTable.csLuaTable.cs.metaMethodWarpsCache.csMethodWarpsCache.cs.metaObjectCasters.csObjectCasters.cs.metaObjectPool.csObjectPool.cs.metaObjectTranslator.csObjectTranslator.cs.metaObjectTranslatorPool.csObjectTranslatorPool.cs.metaRawObject.csRawObject.cs.metaSignatureLoader.csSignatureLoader.cs.metaStaticLuaCallbacks.csStaticLuaCallbacks.cs.metaTemplateEngine.metaLinkXmlGen
Report.csReport.cs.metaTemplate.metaTemplate
LuaClassWrap.tpl.txtLuaClassWrap.tpl.txt.metaLuaClassWrapGCM.tpl.txtLuaClassWrapGCM.tpl.txt.metaLuaDelegateBridge.tpl.txtLuaDelegateBridge.tpl.txt.metaLuaDelegateWrap.tpl.txtLuaDelegateWrap.tpl.txt.metaLuaEnumWrap.tpl.txtLuaEnumWrap.tpl.txt.metaLuaEnumWrapGCM.tpl.txtLuaEnumWrapGCM.tpl.txt.metaLuaInterfaceBridge.tpl.txtLuaInterfaceBridge.tpl.txt.metaLuaRegister.tpl.txtLuaRegister.tpl.txt.metaLuaRegisterGCM.tpl.txtLuaRegisterGCM.tpl.txt.metaLuaWrapPusher.tpl.txtLuaWrapPusher.tpl.txt.metaPackUnpack.tpl.txtPackUnpack.tpl.txt.metaTemplateCommon.lua.txtTemplateCommon.lua.txt.meta
TemplateRef.csTemplateRef.cs.metaTemplateEngine
TypeExtensions.csTypeExtensions.cs.metaUtils.csUtils.cs.metaTutorial
CSharpCallLua.meta
CSharpCallLua
LoadLuaScript.metaLoadLuaScript
ByFile.meta
LuaCallCSharp.metaByFile
ByString.metaByString
Loader.metaLoader
LuaCallCSharp
@ -117,7 +117,9 @@ For example, the following adds a property of GameObject and a method of FileInf
|
||||
[BlackList]
|
||||
public static List<List<string>> BlackList = new List<List<string>>() {
|
||||
new List<string>(){"UnityEngine.GameObject", "networkView"},
|
||||
//new List<string>(){ typeof(UnityEngine.GameObject).FullName, "networkView"},
|
||||
new List<string>(){"System.IO.FileInfo", "GetAccessControl", "System.Security.AccessControl.AccessControlSections"},
|
||||
//new List<string>(){ typeof(System.IO.FileInfo).FullName, "GetAccessControl",typeof(System.Security.AccessControl.AccessControlSections).FullName },
|
||||
};
|
||||
~~~
|
||||
|
||||
|
@ -48,9 +48,7 @@ util.hotfix_ex(class, method_name, fix)
|
||||
|
||||
Like other configurations, there are two methods:
|
||||
|
||||
1. Add Hotfix flag directly in the type;
|
||||
|
||||
2. Configure a list in the static field or property of a static type. Properties can be used to implement more complex configurations, such as whitelisting based on Namespace.
|
||||
Configure a list in the static field or property of a static type. Properties can be used to implement more complex configurations, such as whitelisting based on Namespace.
|
||||
|
||||
~~~csharp
|
||||
public static class HotfixCfg
|
||||
|
@ -7,7 +7,7 @@ Material:
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: logo
|
||||
m_Shader: {fileID: 4800000, guid: 8c3ff126303ac344587210cb9f08ff6c, type: 3}
|
||||
m_Shader: {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
|
@ -1,6 +1,9 @@
|
||||
## C# API
|
||||
|
||||
### LuaEnv类
|
||||
|
||||
#### object[] DoString(string chunk, string chunkName = "chuck", LuaTable env = null)
|
||||
|
||||
描述:
|
||||
|
||||
执行一个代码块。
|
||||
@ -14,7 +17,7 @@
|
||||
|
||||
代码块里return语句的返回值;
|
||||
比如:return 1, “hello”,DoString返回将包含两个object的数组, 一个是double类型的1, 一个是string类型的“hello”
|
||||
|
||||
|
||||
例如:
|
||||
|
||||
LuaEnv luaenv = new LuaEnv();
|
||||
@ -38,7 +41,7 @@
|
||||
|
||||
代表该代码块的delegate或者LuaFunction类;
|
||||
|
||||
#### LuaTable Global;
|
||||
#### LuaTable Global
|
||||
|
||||
描述:
|
||||
|
||||
@ -64,45 +67,44 @@
|
||||
#### void Dispose()
|
||||
|
||||
描述:
|
||||
|
||||
|
||||
Dispose该LuaEnv。
|
||||
|
||||
> LuaEnv的使用建议:全局就一个实例,并在Update中调用GC方法,完全不需要时调用Dispose
|
||||
|
||||
### LuaTable类
|
||||
|
||||
#### T Get<T>(string key)
|
||||
#### `T Get<T>(string key)`
|
||||
|
||||
描述:
|
||||
|
||||
获取在key下,类型为T的value,如果不存在或者类型不匹配,返回null;
|
||||
|
||||
|
||||
#### T GetInPath<T>(string path)
|
||||
#### `T GetInPath<T>(string path)`
|
||||
|
||||
描述:
|
||||
|
||||
和Get的区别是,这个函数会识别path里头的“.”,比如var i = tbl.GetInPath<int>(“a.b.c”)相当于在lua里头执行i = tbl.a.b.c,避免仅为了获取中间变量而多次调用Get,执行效率更高。
|
||||
|
||||
#### void SetInPath<T>(string path, T val)
|
||||
#### `void SetInPath<T>(string path, T val)`
|
||||
|
||||
描述:
|
||||
|
||||
和GetInPaht<T>对应的setter;
|
||||
|
||||
#### void Get<TKey, TValue>(TKey key, out TValue value)
|
||||
#### `void Get<TKey, TValue>(TKey key, out TValue value)`
|
||||
|
||||
描述:
|
||||
|
||||
上面的API的Key都只能是string,而这个API无此限制;
|
||||
|
||||
#### void Set<TKey, TValue>(TKey key, TValue value)
|
||||
#### `void Set<TKey, TValue>(TKey key, TValue value)`
|
||||
|
||||
描述:
|
||||
|
||||
对应Get<TKey, TValue>的setter;
|
||||
|
||||
#### T Cast<T>()
|
||||
#### `T Cast<T>()`
|
||||
|
||||
描述:
|
||||
|
||||
@ -111,12 +113,12 @@
|
||||
#### void SetMetaTable(LuaTable metaTable)
|
||||
|
||||
描述:
|
||||
|
||||
|
||||
设置metaTable为table的metatable
|
||||
|
||||
### LuaFunction类
|
||||
### LuaFunction 类
|
||||
|
||||
> 注意:用该类访问Lua函数会有boxing,unboxing的开销,为了性能考虑,需要频繁调用的地方不要用该类。建议通过table.Get<ABCDelegate>获取一个delegate再调用(假设ABCDelegate是C#的一个delegate)。在使用使用table.Get<ABCDelegate>之前,请先把ABCDelegate加到代码生成列表。
|
||||
> 注意:用该类访问Lua函数会有boxing,unboxing的开销,为了性能考虑,需要频繁调用的地方不要用该类。建议通过 `table.Get<ABCDelegate>` 获取一个 delegate 再调用(假设 `ABCDelegate` 是 C# 的一个 delegate)。在使用使用 `table.Get<ABCDelegate>` 之前,请先把ABCDelegate加到代码生成列表。
|
||||
|
||||
#### object[] Call(params object[] args)
|
||||
|
||||
@ -155,29 +157,27 @@
|
||||
描述:
|
||||
|
||||
访问一个C#静态成员
|
||||
|
||||
|
||||
例如:
|
||||
|
||||
Print(CS.UnityEngine.Vector3.one)
|
||||
|
||||
|
||||
#### CS.namespace.enum.field
|
||||
|
||||
描述:
|
||||
|
||||
|
||||
访问一个枚举值
|
||||
|
||||
#### typeof函数
|
||||
|
||||
描述:
|
||||
|
||||
|
||||
类似C#里头的typeof关键字,返回一个Type对象,比如GameObject.AddComponent其中一个重载需要一个Type参数
|
||||
|
||||
例如:
|
||||
|
||||
newGameObj:AddComponent(typeof(CS.UnityEngine.ParticleSystem))
|
||||
|
||||
|
||||
#### 无符号64位支持
|
||||
|
||||
##### uint64.tostring
|
||||
@ -201,9 +201,9 @@
|
||||
##### uint64.remainder
|
||||
|
||||
描述:
|
||||
|
||||
|
||||
无符号数取模。
|
||||
|
||||
|
||||
##### uint64.parse
|
||||
|
||||
描述:
|
||||
@ -212,24 +212,26 @@
|
||||
#### xlua.structclone
|
||||
|
||||
描述:
|
||||
|
||||
|
||||
克隆一个c#结构体
|
||||
|
||||
#### xlua.private_accessible(class)
|
||||
|
||||
#### xlua.private_accessible(class)
|
||||
|
||||
描述:
|
||||
|
||||
|
||||
让一个类的私有字段,属性,方法等可用
|
||||
例子:
|
||||
|
||||
xlua.private_accessible(CS.UnityEngine.GameObject)
|
||||
xlua.private_accessible(CS.UnityEngine.GameObject)
|
||||
|
||||
#### xlua.get_generic_method
|
||||
|
||||
描述:
|
||||
|
||||
|
||||
获取一个泛型方法
|
||||
例子:
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
local foo_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Foo')
|
||||
local bar_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Bar')
|
||||
|
||||
@ -243,16 +245,16 @@ print(ret)
|
||||
|
||||
-- call static method
|
||||
bar(2, nil)
|
||||
~~~
|
||||
```
|
||||
|
||||
#### cast函数
|
||||
|
||||
描述:
|
||||
|
||||
|
||||
指明以特定的接口访问对象,这在实现类无法访问的时候(比如internal修饰)很有用,这时可以这么来(假设下面的calc对象实现了C#的PerformentTest.ICalc接口)
|
||||
|
||||
例子:
|
||||
|
||||
|
||||
cast(calc, typeof(CS.PerformentTest.ICalc))
|
||||
|
||||
然后就木有其它API了
|
||||
@ -272,7 +274,6 @@ bar(2, nil)
|
||||
|
||||
### 基本数据类型
|
||||
|
||||
|
||||
|C#类型|Lua类型|
|
||||
|-|-|
|
||||
|sbyte,byte,short,ushort,int,uint,double,char,float|number|
|
||||
@ -291,24 +292,24 @@ bar(2, nil)
|
||||
|class或者 struct的实例|userdata,table|
|
||||
|method,delegate|function|
|
||||
|
||||
#### LuaTable:
|
||||
#### LuaTable
|
||||
|
||||
C#侧指明从Lua侧输入(包括C#方法的输入参数或者Lua方法的返回值)LuaTable类型,则要求Lua侧为table。或者Lua侧的table,在C#侧未指明类型的情况下转换成LuaTable。
|
||||
|
||||
#### LuaFunction:
|
||||
#### LuaFunction
|
||||
|
||||
C#侧指明从Lua侧输入(包括C#方法的输入参数或者Lua方法的返回值)LuaFunction类型,则要求Lua侧为function。或者Lua侧的function,在C#侧未指明类型的情况下转换成LuaFunction。
|
||||
|
||||
#### LuaUserData:
|
||||
#### LuaUserData
|
||||
|
||||
对应非C# Managered对象的lua userdata。
|
||||
对应非 C# Managered 对象的lua userdata。
|
||||
|
||||
#### class或者 struct的实例:
|
||||
#### class 或者 struct 的实例
|
||||
|
||||
从C#传一个class或者struct的实例,将映射到Lua的userdata,并通过__index访问该userdata的成员
|
||||
C#侧指明从Lua侧输入指定类型对象,Lua侧为该类型实例的userdata可以直接使用;如果该指明类型有默认构造函数,Lua侧是table则会自动转换,转换规则是:调用构造函数构造实例,并用table对应字段转换到c#对应值后赋值各成员。
|
||||
|
||||
#### method, delegate:
|
||||
#### method, delegate
|
||||
|
||||
成员方法以及delegate都是对应lua侧的函数。
|
||||
C#侧的普通参数以及引用参数,对应lua侧函数参数;C#侧的返回值对应于Lua的第一个返回值;引用参数和out参数则按序对应于Lua的第2到第N个参数。
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
1. 获取一个全局基本数据类型
|
||||
访问LuaEnv.Global就可以了,上面有个模版Get方法,可指定返回的类型。
|
||||
|
||||
|
||||
luaenv.Global.Get<int>("a")
|
||||
luaenv.Global.Get<string>("b")
|
||||
luaenv.Global.Get<bool>("c")
|
||||
@ -66,7 +66,7 @@
|
||||
那有没有引用方式的映射呢?有,下面这个就是:
|
||||
|
||||
2. 映射到一个interface
|
||||
|
||||
|
||||
这种方式依赖于生成代码(如果没生成代码会抛InvalidCastException异常),代码生成器会生成这个interface的实例,如果get一个属性,生成代码会get对应的table字段,如果set属性也会设置对应的字段。甚至可以通过interface的方法访问lua的函数。
|
||||
|
||||
3. 更轻量级的by value方式:映射到Dictionary<>,List<>
|
||||
@ -74,7 +74,7 @@
|
||||
不想定义class或者interface的话,可以考虑用这个,前提table下key和value的类型都是一致的。
|
||||
|
||||
4. 另外一种by ref方式:映射到LuaTable类
|
||||
|
||||
|
||||
这种方式好处是不需要生成代码,但也有一些问题,比如慢,比方式2要慢一个数量级,比如没有类型检查。
|
||||
|
||||
3. 访问一个全局的function
|
||||
@ -93,7 +93,7 @@
|
||||
delegate的使用就更简单了,直接像个函数那样用就可以了。
|
||||
|
||||
2. 映射到LuaFunction
|
||||
|
||||
|
||||
这种方式的优缺点刚好和第一种相反。
|
||||
使用也简单,LuaFunction上有个变参的Call函数,可以传任意类型,任意个数的参数,返回值是object的数组,对应于lua的多返回值。
|
||||
|
||||
@ -101,9 +101,9 @@
|
||||
|
||||
1. 访问lua全局数据,特别是table以及function,代价比较大,建议尽量少做,比如在初始化时把要调用的lua function获取一次(映射到delegate)后,保存下来,后续直接调用该delegate即可。table也类似。
|
||||
|
||||
2. 如果lua测的实现的部分都以delegate和interface的方式提供,使用方可以完全和xLua解耦:由一个专门的模块负责xlua的初始化以及delegate、interface的映射,然后把这些delegate和interface设置到要用到它们的地方。
|
||||
2. 如果lua侧的实现的部分都以delegate和interface的方式提供,使用方可以完全和xLua解耦:由一个专门的模块负责xlua的初始化以及delegate、interface的映射,然后把这些delegate和interface设置到要用到它们的地方。
|
||||
|
||||
### Lua调用C#
|
||||
### Lua 调用 C#
|
||||
|
||||
> 本章节涉及到的实例均在XLua\Tutorial\LuaCallCSharp下
|
||||
|
||||
@ -167,11 +167,12 @@ xlua支持(通过派生类)访问基类的静态属性,静态方法,(
|
||||
|
||||
##### 参数的输入输出属性(out,ref)
|
||||
|
||||
Lua调用测的参数处理规则:C#的普通参数算一个输入形参,ref修饰的算一个输入形参,out不算,然后从左往右对应lua 调用测的实参列表;
|
||||
Lua调用侧的参数处理规则:C#的普通参数算一个输入形参,ref修饰的算一个输入形参,out不算,然后从左往右对应lua 调用侧的实参列表;
|
||||
|
||||
Lua调用测的返回值处理规则:C#函数的返回值(如果有的话)算一个返回值,out算一个返回值,ref算一个返回值,然后从左往右对应lua的多返回值。
|
||||
Lua调用侧的返回值处理规则:C#函数的返回值(如果有的话)算一个返回值,out算一个返回值,ref算一个返回值,然后从左往右对应lua的多返回值。
|
||||
|
||||
##### 重载方法
|
||||
|
||||
直接通过不同的参数类型进行重载函数的访问,例如:
|
||||
|
||||
testobj:TestFunc(100)
|
||||
@ -190,6 +191,7 @@ Lua调用测的返回值处理规则:C#函数的返回值(如果有的话)
|
||||
和C#调用有默认值参数的函数一样,如果所给的实参少于形参,则会用默认值补上。
|
||||
|
||||
##### 可变参数方法
|
||||
|
||||
对于C#的如下方法:
|
||||
|
||||
void VariableParamsFunc(int a, params string[] strs)
|
||||
|
@ -1,22 +1,22 @@
|
||||
# 通用字节码
|
||||
|
||||
不少项目希望把项目的lua源码通过luac编译后加载,但官方lua有个缺陷:字节码是分32位和64位版本的,换句话你32位lua环境只能跑32位luac编译出来的东西。
|
||||
不少项目希望把项目的 lua 源码通过 luac 编译后加载,但官方 lua 有个缺陷:字节码是分 32 位和 64 位版本的,换句话你 32 位 lua 环境只能跑 32 位 luac 编译出来的东西。
|
||||
|
||||
为此,xLua尝试对lua源码做了少许改造,可以编译一份字节码,跨平台使用。
|
||||
为此,xLua 尝试对 lua 源码做了少许改造,可以编译一份字节码,跨平台使用。
|
||||
|
||||
## 注意事项
|
||||
|
||||
* 1、如果你做了本文所描述的改动,你的xLua将加载不了官方luac所编译的字节码;
|
||||
* 1、如果你做了本文所描述的改动,你的 xLua 将加载不了官方 luac 所编译的字节码;
|
||||
|
||||
* 2、截至2018/9/14,已知此改法在一个上线一个多月的项目正常运行,但不代表此改法在任何情况都没问题。
|
||||
* 2、截至 2018/9/14,已知此改法在一个上线一个多月的项目正常运行,但不代表此改法在任何情况都没问题。
|
||||
|
||||
## 操作指南
|
||||
|
||||
### 1、编译xlua的Plugins
|
||||
### 1、编译 xlua 的 Plugins
|
||||
|
||||
修改各平台编译脚本,在cmake命令加上-DLUAC_COMPATIBLE_FORMAT=ON参数,以make_win64_lua53.bat为例,修改后是这样的:
|
||||
修改各平台编译脚本,在 cmake 命令加上 `-DLUAC_COMPATIBLE_FORMAT=ON` 参数,以 make_win64_lua53.bat 为例,修改后是这样的:
|
||||
|
||||
~~~bash
|
||||
```bash
|
||||
mkdir build64 & pushd build64
|
||||
cmake -DLUAC_COMPATIBLE_FORMAT=ON -G "Visual Studio 14 2015 Win64" ..
|
||||
popd
|
||||
@ -24,18 +24,18 @@ cmake --build build64 --config Release
|
||||
md plugin_lua53\Plugins\x86_64
|
||||
copy /Y build64\Release\xlua.dll plugin_lua53\Plugins\x86_64\xlua.dll
|
||||
pause
|
||||
~~~
|
||||
```
|
||||
|
||||
用修改后的编译脚本重新编译各平台的xlua库,并覆盖原Plugins目录下对应文件。
|
||||
用修改后的编译脚本重新编译各平台的 xlua 库,并覆盖原 Plugins 目录下对应文件。
|
||||
|
||||
## 2、编译能生成兼容格式的luac(后续只能用这特定的luac和步骤1的Plugins配套使用)
|
||||
|
||||
到[这里](../../../build/luac/),如果你想编译window版本的,执行make_win64.bat,如果你要编译mac或者linux的,用make_unix.sh
|
||||
到[这里](../../../build/luac/),如果你想编译 Windows 版本的,执行 make_win64.bat,如果你要编译 Mac 或者 Linux 的,用make_unix.sh
|
||||
|
||||
## 3、加载字节码
|
||||
|
||||
通过CustomLoader加载即可,CustomLoader的详细情况请看教程。这个步骤常犯的错误是用某种Encoding去加载二进制文件,这会破坏lua字节码文件格式。谨记得以二进制方式加载。
|
||||
通过 CustomLoader 加载即可,CustomLoader 的详细情况请看教程。这个步骤常犯的错误是用某种Encoding去加载二进制文件,这会破坏lua字节码文件格式。谨记得以二进制方式加载。
|
||||
|
||||
## PS: OpCode修改
|
||||
|
||||
有项目想修改为专用格式的字节码,直接在lua源码(目前是lua-5.3.5)上修改后,重新执行上述1、2操作步骤即可。
|
||||
有项目想修改为专用格式的字节码,直接在 lua 源码(目前是lua-5.3.5)上修改后,重新执行上述1、2操作步骤即可。
|
||||
|
@ -13,7 +13,7 @@ xLua所有的配置都支持三种方式:打标签;静态列表;动态列
|
||||
|
||||
xLua用白名单来指明生成哪些代码,而白名单通过attribute来配置,比如你想从lua调用c#的某个类,希望生成适配代码,你可以为这个类型打一个LuaCallCSharp标签:
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
|
||||
[LuaCallCSharp]
|
||||
publicclassA
|
||||
@ -21,7 +21,7 @@ publicclassA
|
||||
|
||||
}
|
||||
|
||||
~~~
|
||||
```
|
||||
|
||||
该方式方便,但在il2cpp下会增加不少的代码量,不建议使用。
|
||||
|
||||
@ -29,7 +29,7 @@ publicclassA
|
||||
|
||||
有时我们无法直接给一个类型打标签,比如系统api,没源码的库,或者实例化的泛化类型,这时你可以在一个静态类里声明一个静态字段,该字段的类型除BlackList和AdditionalProperties之外只要实现了IEnumerable<Type>就可以了(这两个例外后面具体会说),然后为这字段加上标签:
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
|
||||
[LuaCallCSharp]
|
||||
public static List<Type> mymodule_lua_call_cs_list = new List<Type>()
|
||||
@ -38,7 +38,7 @@ public static List<Type> mymodule_lua_call_cs_list = new List<Type>()
|
||||
typeof(Dictionary<string, int>),
|
||||
};
|
||||
|
||||
~~~
|
||||
```
|
||||
|
||||
这个字段需要放到一个 **静态类** 里头,建议放到 **Editor目录** 。
|
||||
|
||||
@ -46,7 +46,7 @@ public static List<Type> mymodule_lua_call_cs_list = new List<Type>()
|
||||
|
||||
声明一个静态属性,打上相应的标签即可。
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
|
||||
[Hotfix]
|
||||
public static List<Type> by_property
|
||||
@ -59,7 +59,7 @@ public static List<Type> by_property
|
||||
}
|
||||
}
|
||||
|
||||
~~~
|
||||
```
|
||||
|
||||
Getter是代码,你可以实现很多效果,比如按名字空间配置,按程序集配置等等。
|
||||
|
||||
@ -79,7 +79,7 @@ xLua只会生成加了该配置的类型,不会自动生成其父类的适配
|
||||
|
||||
一个C#类型类型加了这个配置,xLua会生成link.xml阻止il2cpp的代码剪裁。
|
||||
|
||||
对于扩展方法,必须加上LuaCallCSharp或者ReflectionUse才可以被访问到。
|
||||
对于扩展方法,必须加上 `LuaCallCSharp` 或者 `ReflectionUse` 才可以被访问到。
|
||||
|
||||
建议所有要在Lua访问的类型,要么加LuaCallCSharp,要么加上ReflectionUse,这才能够保证在各平台都能正常运行。
|
||||
|
||||
@ -87,7 +87,7 @@ xLua只会生成加了该配置的类型,不会自动生成其父类的适配
|
||||
|
||||
指明一个类里头的部分函数、字段、属性不生成代码,通过反射访问。
|
||||
|
||||
只能标准Dictionary<Type, List<string>>的field或者property。key指明的是生效的类,value是一个列表,配置的是不生成代码的函数、字段、属性的名字。
|
||||
只能标准 `Dictionary<Type, List<string>>` 的field或者property。key指明的是生效的类,value是一个列表,配置的是不生成代码的函数、字段、属性的名字。
|
||||
|
||||
和ReflectionUse的区别是:1、ReflectionUse指明的是整个类;2、当第一次访问一个函数(字段、属性)时,ReflectionUse会把整个类都wrap,而DoNotGen只wrap该函数(字段、属性),换句话DoNotGen更lazy一些;
|
||||
|
||||
@ -99,7 +99,7 @@ xLua只会生成加了该配置的类型,不会自动生成其父类的适配
|
||||
|
||||
### XLua.GCOptimize
|
||||
|
||||
一个C#纯值类型(注:指的是一个只包含值类型的struct,可以嵌套其它只包含值类型的struct)或者C#枚举值加上了这个配置。xLua会为该类型生成gc优化代码,效果是该值类型在lua和c#间传递不产生(C#)gc alloc,该类型的数组访问也不产生gc。各种无GC的场景,可以参考05\_NoGc例子。
|
||||
一个C#纯值类型(注:指的是一个只包含值类型的struct,可以嵌套其它只包含值类型的struct)或者C#枚举值加上了这个配置。xLua会为该类型生成gc优化代码,效果是该值类型在lua和c#间传递不产生(C#)gc alloc,该类型的数组访问也不产生gc。各种无GC的场景,可以参考 `05_Gc` 例子。
|
||||
|
||||
除枚举之外,包含无参构造函数的复杂类型,都会生成lua table到该类型,以及改类型的一维数组的转换代码,这将会优化这个转换的性能,包括更少的gc alloc。
|
||||
|
||||
@ -107,7 +107,7 @@ xLua只会生成加了该配置的类型,不会自动生成其父类的适配
|
||||
|
||||
这个是GCOptimize的扩展配置,有的时候,一些struct喜欢把field做成是私有的,通过property来访问field,这时就需要用到该配置(默认情况下GCOptimize只对public的field打解包)。
|
||||
|
||||
标签方式比较简单,配置方式复杂一点,要求是Dictionary<Type, List<string>>类型,Dictionary的Key是要生效的类型,Value是属性名列表。可以参考XLua对几个UnityEngine下值类型的配置,SysGCOptimize类。
|
||||
标签方式比较简单,配置方式复杂一点,要求是 `Dictionary<Type, List<string>>` 类型,Dictionary 的 Key 是要生效的类型,Value 是属性名列表。可以参考XLua对几个UnityEngine下值类型的配置,SysGCOptimize类。
|
||||
|
||||
### XLua.BlackList
|
||||
|
||||
@ -115,19 +115,21 @@ xLua只会生成加了该配置的类型,不会自动生成其父类的适配
|
||||
|
||||
标签方式比较简单,对应的成员上加就可以了。
|
||||
|
||||
由于考虑到有可能需要把重载函数的其中一个重载列入黑名单,配置方式比较复杂,类型是List<List<string>>,对于每个成员,在第一层List有一个条目,第二层List是个string的列表,第一个string是类型的全路径名,第二个string是成员名,如果成员是一个方法,还需要从第三个string开始,把其参数的类型全路径全列出来。
|
||||
由于考虑到有可能需要把重载函数的其中一个重载列入黑名单,配置方式比较复杂,类型是 `List<List<string>>`,对于每个成员,在第一层List有一个条目,第二层List是个string的列表,第一个string是类型的全路径名,第二个string是成员名,如果成员是一个方法,还需要从第三个string开始,把其参数的类型全路径全列出来。
|
||||
|
||||
例如下面是对GameObject的一个属性以及FileInfo的一个方法列入黑名单:
|
||||
例如下面是对 GameObject 的一个属性以及FileInfo的一个方法列入黑名单:
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
|
||||
[BlackList]
|
||||
public static List<List<string>> BlackList = new List<List<string>>() {
|
||||
new List<string>(){"UnityEngine.GameObject", "networkView"},
|
||||
//new List<string>(){ typeof(UnityEngine.GameObject).FullName, "networkView"},
|
||||
new List<string>(){"System.IO.FileInfo", "GetAccessControl", "System.Security.AccessControl.AccessControlSections"},
|
||||
//new List<string>(){ typeof(System.IO.FileInfo).FullName, "GetAccessControl",typeof(System.Security.AccessControl.AccessControlSections).FullName },
|
||||
};
|
||||
|
||||
~~~
|
||||
```
|
||||
|
||||
### 下面是生成期配置,必须放到Editor目录下
|
||||
|
||||
|
@ -16,7 +16,7 @@ xLua的生成引擎支持二次开发,你可以利用它来生成一些文本
|
||||
|
||||
示例:
|
||||
|
||||
~~~xml
|
||||
```xml
|
||||
<%
|
||||
require "TemplateCommon"
|
||||
%>
|
||||
@ -30,47 +30,47 @@ require "TemplateCommon"
|
||||
</assembly>
|
||||
<%end)%>
|
||||
</linker>
|
||||
~~~
|
||||
```
|
||||
|
||||
TemplateCommon有一些预定义的函数可以使用,比如ForEachCsList,可以搜索下工程的TemplateCommon.lua.txt看下有那些函数可以用,就普通的lua而已,你自己写一套也可以。
|
||||
|
||||
## API
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
public static void CSObjectWrapEditor.Generator.CustomGen(string template_src, GetTasks get_tasks)
|
||||
~~~
|
||||
```
|
||||
|
||||
* template_src : 模版的源码;
|
||||
* get_tasks : 回调函数,类型是GetTasks,用来接受用户的配置,返回需要注入到模版的数据以及文件的输出流;
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
public delegate IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig user_cfg);
|
||||
~~~
|
||||
```
|
||||
|
||||
* lua_env : LuaEnv对象,因为返回的模版数据需要放到LuaTable,需要用到LuaEnv.NewTable;
|
||||
* user_cfg : 用户的配置;
|
||||
* return : 返回值中,CustomGenTask代表的是一个生成文件,而IEnumerable类型表示同一个模版可以生成多个文件;
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
public struct UserConfig
|
||||
{
|
||||
public IEnumerable<Type> LuaCallCSharp;
|
||||
public IEnumerable<Type> CSharpCallLua;
|
||||
public IEnumerable<Type> ReflectionUse;
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
public struct CustomGenTask
|
||||
{
|
||||
public LuaTable Data;
|
||||
public TextWriter Output;
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
public static IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig user_cfg)
|
||||
{
|
||||
LuaTable data = lua_env.NewTable();
|
||||
@ -86,7 +86,7 @@ public static IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig use
|
||||
false, Encoding.UTF8)
|
||||
};
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
* 这里只生成一个文件,故只返回一个CustomGenTask;
|
||||
* data就是模版要使用的数据,这里塞了一个assembly_infos字段,这个字段如何使用可以回头看看模版部分;
|
||||
@ -97,13 +97,13 @@ public static IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig use
|
||||
|
||||
示例:
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
[GenCodeMenu]//加到Generate Code菜单里头
|
||||
public static void GenLinkXml()
|
||||
{
|
||||
Generator.CustomGen(ScriptableObject.CreateInstance<LinkXmlGen>().Template.text, GetTasks);
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
|
||||
ps:以上所有相关代码都在XLua\Src\Editor\LinkXmlGen目录下,也正是文章开头说的link.xml的生成功能的实现。
|
||||
|
@ -68,7 +68,13 @@ ios和osx需要在mac下编译。
|
||||
|
||||
## 报类似“xlua.access, no field __Hitfix0_Update”的错误怎么解决?
|
||||
|
||||
按[Hotfix操作指南](hotfix.md)一步步操作。
|
||||
按[Hotfix操作指南](hotfix.md)一步步操作,以及注意事项。确保上述步骤完成后,可尝试使用[解决方案](https://github.com/Tencent/xLua/issues/850)。
|
||||
|
||||
出现这报错,肯定是这个导致的:最终包的这个方法(函数)没注入。
|
||||
|
||||
但造成“最终包的这个方法(函数)没注入”的原因会有很多:比如没按文档操作,注入失败,比如Hotfix列表漏了这个类,比如你的打包脚本在注入后,又触发了重新编译,覆盖了注入结果。。。
|
||||
|
||||
统一的解决方式是找出并解决导致“最终包的这个方法(函数)没注入”的具体原因。
|
||||
|
||||
## visual studio 2017下编译UWP原生库
|
||||
|
||||
@ -90,6 +96,8 @@ visual studio 2017需要安装:1、“工作负载”下的“通用Window平
|
||||
|
||||
如果编辑器下没问题,发布到手机报这错,表示你发布前没生成代码(执行“XLua/Generate Code”)。
|
||||
|
||||
如果你Unity版本大于或等于2018,看下前面兼容性的章节。
|
||||
|
||||
## unity5.5以上执行"XLua/Hotfix Inject In Editor"菜单会提示"WARNING: The runtime version supported by this application is unavailable."
|
||||
|
||||
这是因为注入工具是用.net3.5编译,而unity5.5意思MonoBleedingEdge的mono环境并没3.5支持导致的,不过一般而言都向下兼容,目前为止也没发现该warning带来什么问题。
|
||||
@ -192,6 +200,7 @@ end)
|
||||
```
|
||||
|
||||
3、如果xlua版本大于2.1.12的话,新增反射调用泛型方法的支持(有一定的限制,看后面的说明),比如对于这么个C#类型:
|
||||
|
||||
```csharp
|
||||
public class GetGenericMethodTest
|
||||
{
|
||||
@ -214,7 +223,9 @@ public class GetGenericMethodTest
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
在lua那这么调用:
|
||||
|
||||
```lua
|
||||
local foo_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Foo')
|
||||
local bar_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Bar')
|
||||
@ -252,12 +263,12 @@ bar(2, nil)
|
||||
|
||||
如果你的版本大于2.1.11,可以用get_Item来获取值,用set_Item来设置值。要注意只有this[string field]或者this[object field]才有这两个替代api,其它类型的key是没有的。
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
dic:set_Item('a', 1)
|
||||
dic:set_Item('b', 2)
|
||||
print(dic:get_Item('a'))
|
||||
print(dic:get_Item('b'))
|
||||
~~~
|
||||
```
|
||||
|
||||
如果你的版本小于或等于2.1.11,建议直接方法该操作符的等效方法,比如Dictionary的TryGetValue,如果该方法没有提供,可以在C#那通过Extension method封装一个使用。
|
||||
|
||||
@ -267,7 +278,7 @@ print(dic:get_Item('b'))
|
||||
|
||||
对应这种情况,可以为UnityEngine.Object写一个扩展方法:
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
[LuaCallCSharp]
|
||||
[ReflectionUse]
|
||||
public static class UnityEngineObjectExtention
|
||||
@ -277,35 +288,35 @@ public static class UnityEngineObjectExtention
|
||||
return o == null;
|
||||
}
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
然后在lua那你对所有UnityEngine.Object实例都使用IsNull判断
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
print(go:GetComponent('Animator'):IsNull())
|
||||
~~~
|
||||
```
|
||||
|
||||
## 泛型实例怎么构造
|
||||
|
||||
涉及的类型都在mscorlib,Assembly-CSharp程序集的话,泛型实例的构造和普通类型是一样的,都是CS.namespace.typename(),可能比较特殊的是typename的表达,泛型实例的typename的表达包含了标识符非法符号,最后一部分要换成["typename"],以List<string>为例
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
local lst = CS.System.Collections.Generic["List`1[System.String]"]()
|
||||
~~~
|
||||
```
|
||||
|
||||
如果某个泛型实例的typename不确定,可以在C#测打印下typeof(不确定的类型).ToString()
|
||||
|
||||
如果涉及mscorlib,Assembly-CSharp程序集之外的类型的话,可以用C#的反射来做:
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
local dic = CS.System.Activator.CreateInstance(CS.System.Type.GetType('System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UnityEngine.Vector3, UnityEngine]],mscorlib'))
|
||||
dic:Add('a', CS.UnityEngine.Vector3(1, 2, 3))
|
||||
print(dic:TryGetValue('a'))
|
||||
~~~
|
||||
```
|
||||
|
||||
如果你的xLua版本大于v2.1.12,将会有更漂亮的表达方式
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
-- local List_String = CS.System.Collections.Generic['List<>'](CS.System.String) -- another way
|
||||
local List_String = CS.System.Collections.Generic.List(CS.System.String)
|
||||
local lst = List_String()
|
||||
@ -314,7 +325,7 @@ local Dictionary_String_Vector3 = CS.System.Collections.Generic.Dictionary(CS.Sy
|
||||
local dic = Dictionary_String_Vector3()
|
||||
dic:Add('a', CS.UnityEngine.Vector3(1, 2, 3))
|
||||
print(dic:TryGetValue('a'))
|
||||
~~~
|
||||
```
|
||||
|
||||
|
||||
## 调用LuaEnv.Dispose时,报“try to dispose a LuaEnv with C# callback!”错是什么原因?
|
||||
@ -333,17 +344,17 @@ print(dic:TryGetValue('a'))
|
||||
|
||||
xlua提供了一个工具函数来帮助你找到被C#引用着的lua函数,util.print_func_ref_by_csharp,使用很简单,执行如下lua代码:
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
local util = require 'xlua.util'
|
||||
util.print_func_ref_by_csharp()
|
||||
~~~
|
||||
```
|
||||
|
||||
可以看到控制台有类似这样的输出,下面第一行表示有一个在main.lua的第2行定义的函数被C#引用着
|
||||
|
||||
~~~bash
|
||||
```bash
|
||||
LUA: main.lua:2
|
||||
LUA: main.lua:13
|
||||
~~~
|
||||
```
|
||||
|
||||
## 调用LuaEnv.Dispose崩溃
|
||||
|
||||
@ -358,14 +369,14 @@ LUA: main.lua:13
|
||||
|
||||
用util.hotfix_ex,可以调用原先的C#逻辑
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
local util = require 'xlua.util'
|
||||
util.hotfix_ex(CS.HotfixTest, 'Add', function(self, a, b)
|
||||
local org_sum = self:Add(a, b)
|
||||
print('org_sum', org_sum)
|
||||
return a + b
|
||||
end)
|
||||
~~~
|
||||
```
|
||||
|
||||
## 怎么把C#的函数赋值给一个委托字段
|
||||
|
||||
@ -375,7 +386,7 @@ end)
|
||||
|
||||
比如如下C#代码
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
public class TestClass
|
||||
{
|
||||
public void Foo(int a)
|
||||
@ -387,10 +398,10 @@ public class TestClass
|
||||
}
|
||||
}
|
||||
public delegate void TestDelegate(int a);
|
||||
~~~
|
||||
```
|
||||
|
||||
你可以指明用Foo函数创建一个TestDelegate实例
|
||||
~~~lua
|
||||
```lua
|
||||
local util = require 'xlua.util'
|
||||
|
||||
local d1 = util.createdelegate(CS.TestDelegate, obj, CS.TestClass, 'Foo', {typeof(CS.System.Int32)}) --由于Foo是实例方法,所以参数2需要传TestClass实例
|
||||
@ -398,7 +409,7 @@ local d2 = util.createdelegate(CS.TestDelegate, nil, CS.TestClass, 'SFoo', {type
|
||||
|
||||
obj_has_TestDelegate.field = d1 + d2 --到时调用field的时候将会触发Foo和SFoo,这不会经过Lua适配
|
||||
|
||||
~~~
|
||||
```
|
||||
|
||||
## 为什么有时Lua错误直接中断了而没错误信息?
|
||||
|
||||
@ -408,15 +419,15 @@ obj_has_TestDelegate.field = d1 + d2 --到时调用field的时候将会触发Foo
|
||||
|
||||
把类似下面的代码:
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
coroutine.resume(co, ...)
|
||||
~~~
|
||||
```
|
||||
|
||||
改为:
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
assert(coroutine.resume(co, ...))
|
||||
~~~
|
||||
```
|
||||
|
||||
2、上层catch后,不打印
|
||||
|
||||
@ -432,7 +443,7 @@ assert(coroutine.resume(co, ...))
|
||||
|
||||
可以通过xlua.tofunction结合反射来处理,xlua.tofunction输入一个MethodBase对象,返回一个lua函数。比如下面的C#代码:
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
class TestOverload
|
||||
{
|
||||
public int Add(int a, int b)
|
||||
@ -447,11 +458,11 @@ class TestOverload
|
||||
return (short)(a + b);
|
||||
}
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
我们可以这么调用指定重载:
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
local m1 = typeof(CS.TestOverload):GetMethod('Add', {typeof(CS.System.Int16), typeof(CS.System.Int16)})
|
||||
local m2 = typeof(CS.TestOverload):GetMethod('Add', {typeof(CS.System.Int32), typeof(CS.System.Int32)})
|
||||
local f1 = xlua.tofunction(m1) --切记对于同一个MethodBase,只tofunction一次,然后重复使用
|
||||
@ -461,7 +472,7 @@ local obj = CS.TestOverload()
|
||||
|
||||
f1(obj, 1, 2) --调用short版本,成员方法,所以要传对象,静态方法则不需要
|
||||
f2(obj, 1, 2) --调用int版本
|
||||
~~~
|
||||
```
|
||||
|
||||
注意:xlua.tofunction由于使用不太方便,以及使用了反射,所以建议做作为临时方案,尽量用封装的方法来解决。
|
||||
|
||||
@ -511,3 +522,10 @@ f2(obj, 1, 2) --调用int版本
|
||||
|
||||
常见的不明显的多线程的场景,比如c#异步socket,对象析构函数等。
|
||||
|
||||
## maOS10.15以上,启动unity的时候提示xlua.bundle损坏,移动到废纸篓
|
||||
|
||||
执行
|
||||
|
||||
```bash
|
||||
sudo xattr -r -d com.apple.quarantine xlua.bundle
|
||||
```
|
||||
|
@ -3,67 +3,67 @@
|
||||
## 总体
|
||||
|
||||
* Lua虚拟机支持
|
||||
* Lua5.3
|
||||
* Luajit2.1
|
||||
* Lua5.3
|
||||
* Luajit2.1
|
||||
* Unity3D版本支持
|
||||
* 各版本均支持
|
||||
* 各版本均支持
|
||||
* 平台支持
|
||||
* windows 64/32
|
||||
* android
|
||||
* ios 64/32/bitcode
|
||||
* osx
|
||||
* uwp
|
||||
* webgl
|
||||
* windows 64/32
|
||||
* android
|
||||
* ios 64/32/bitcode
|
||||
* osx
|
||||
* uwp
|
||||
* webgl
|
||||
* 互访技术
|
||||
* 生成适配代码
|
||||
* 反射
|
||||
* 生成适配代码
|
||||
* 反射
|
||||
* 易用性
|
||||
* 解压即可用
|
||||
* 开发期无需生成代码
|
||||
* 生成代码和反射间可无缝切换
|
||||
* 更简单的无GC api
|
||||
* 菜单简单易懂
|
||||
* 配置可以多份,按模块划分,也可以直接在目标类型上打Attribute标签
|
||||
* 自动生成link.xml防止代码剪裁
|
||||
* Plugins部分采用cmake编译,更简单
|
||||
* 核心代码不依赖生成代码,可以随时删除生成目录
|
||||
* 解压即可用
|
||||
* 开发期无需生成代码
|
||||
* 生成代码和反射间可无缝切换
|
||||
* 更简单的无GC api
|
||||
* 菜单简单易懂
|
||||
* 配置可以多份,按模块划分,也可以直接在目标类型上打Attribute标签
|
||||
* 自动生成link.xml防止代码剪裁
|
||||
* Plugins部分采用cmake编译,更简单
|
||||
* 核心代码不依赖生成代码,可以随时删除生成目录
|
||||
* 性能
|
||||
* Lazyload技术,避免用不上的类型的开销
|
||||
* lua函数映射到c# delegate,lua table映射到interface,可实现接口层面无C# gc alloc开销
|
||||
* 所有基本值类型,所有枚举,字段都是值类型的struct,在Lua和C#间传递无C# gc alloc
|
||||
* LuaTable,LuaFunction提供无gc访问接口
|
||||
* 通过代码生成期的静态分析,生成最优代码
|
||||
* 支持C#和Lua间指针传递
|
||||
* 自动解除已经Destroy的UnityEngine.Object的引用
|
||||
* Lazyload技术,避免用不上的类型的开销
|
||||
* lua函数映射到c# delegate,lua table映射到interface,可实现接口层面无C# gc alloc开销
|
||||
* 所有基本值类型,所有枚举,字段都是值类型的struct,在Lua和C#间传递无C# gc alloc
|
||||
* LuaTable,LuaFunction提供无gc访问接口
|
||||
* 通过代码生成期的静态分析,生成最优代码
|
||||
* 支持C#和Lua间指针传递
|
||||
* 自动解除已经Destroy的UnityEngine.Object的引用
|
||||
* 扩展性
|
||||
* 不用改代码就可以加入Lua第三方扩展
|
||||
* 生成引擎提供接口做二次开发
|
||||
* 不用改代码就可以加入Lua第三方扩展
|
||||
* 生成引擎提供接口做二次开发
|
||||
|
||||
## 支持为如下C#实现打补丁
|
||||
|
||||
* 构造函数
|
||||
* 析构函数
|
||||
* 成员函数
|
||||
* 静态函数
|
||||
* 泛化函数
|
||||
* 操作符重载
|
||||
* 成员属性
|
||||
* 静态属性
|
||||
* 事件
|
||||
|
||||
* 构造函数
|
||||
* 析构函数
|
||||
* 成员函数
|
||||
* 静态函数
|
||||
* 泛化函数
|
||||
* 操作符重载
|
||||
* 成员属性
|
||||
* 静态属性
|
||||
* 事件
|
||||
|
||||
## Lua代码加载
|
||||
|
||||
* 加载字符串
|
||||
* 支持加载后立即执行
|
||||
* 支持加载后返回一个delegate或者LuaFunction,调用delegate或者LuaFunction后可传脚本参数
|
||||
* 支持加载后立即执行
|
||||
* 支持加载后返回一个delegate或者LuaFunction,调用delegate或者LuaFunction后可传脚本参数
|
||||
* Resources目录的文件
|
||||
* 直接require
|
||||
* 直接require
|
||||
* 自定义loader
|
||||
* Lua里头require时触发
|
||||
* require参数透传给loader,loader读取Lua代码返回
|
||||
* Lua里头require时触发
|
||||
* require参数透传给loader,loader读取Lua代码返回
|
||||
* Lua原有的方式
|
||||
* Lua原有的方式都保留
|
||||
|
||||
* Lua原有的方式都保留
|
||||
|
||||
## Lua调用C#
|
||||
|
||||
* 创建C#对象
|
||||
@ -72,58 +72,58 @@
|
||||
* C#成员属性,字段
|
||||
* C#成员方法
|
||||
* C#继承
|
||||
* 子类对象可以直接调用父类的方法,访问父类属性
|
||||
* 子类模块可以直接调用父类的静态方法,静态属性
|
||||
* 子类对象可以直接调用父类的方法,访问父类属性
|
||||
* 子类模块可以直接调用父类的静态方法,静态属性
|
||||
* 扩展方法(Extension methods)
|
||||
* 就像普通成员方法一样使用
|
||||
* 就像普通成员方法一样使用
|
||||
* 参数的输入输出属性(out,ref)
|
||||
* out对应一个lua返回值
|
||||
* ref对应一个lua参数以及一个lua返回值
|
||||
* out对应一个lua返回值
|
||||
* ref对应一个lua参数以及一个lua返回值
|
||||
* 函数重载
|
||||
* 支持重载
|
||||
* 由于lua数据类型远比C#要少,会出现无法判断的情况,可通过扩展方法来来调用。
|
||||
* 支持重载
|
||||
* 由于lua数据类型远比C#要少,会出现无法判断的情况,可通过扩展方法来来调用。
|
||||
* 操作符重载
|
||||
* 支持的操作符:+,-,*,/,==,一元-,<,<=, %,[]
|
||||
* 其它操作符可以借助扩展方法调用
|
||||
* 支持的操作符:+,-,*,/,==,一元-,<,<=, %,[]
|
||||
* 其它操作符可以借助扩展方法调用
|
||||
* 参数默认值
|
||||
* C#参数有默认值,在lua可以不传
|
||||
* C#参数有默认值,在lua可以不传
|
||||
* 可变参数
|
||||
* 在对应可变参数部分,直接输入一个个参数即可,不需要把这些参数扩到一个数组里头
|
||||
* 在对应可变参数部分,直接输入一个个参数即可,不需要把这些参数扩到一个数组里头
|
||||
* 泛化方法调用
|
||||
* 静态方法可以自行封装使用
|
||||
* 成员函数可通过扩展方法封装使用
|
||||
* 静态方法可以自行封装使用
|
||||
* 成员函数可通过扩展方法封装使用
|
||||
* 枚举类型
|
||||
* 数字或字符串到枚举的转换
|
||||
* 数字或字符串到枚举的转换
|
||||
* delegate
|
||||
* 调用一个C# delegate
|
||||
* +操作符
|
||||
* -操作符
|
||||
* 把一个lua函数作为一个c# delegate传递给c#
|
||||
* 调用一个C# delegate
|
||||
* +操作符
|
||||
* -操作符
|
||||
* 把一个lua函数作为一个c# delegate传递给c#
|
||||
* event
|
||||
* 增加事件回调
|
||||
* 移除事件回调
|
||||
* 增加事件回调
|
||||
* 移除事件回调
|
||||
* 64位整数
|
||||
* 传递无gc而且无精度损失
|
||||
* lua53下使用原生64位支持
|
||||
* 可以和number运算
|
||||
* 以java的方式支持无符号64位整数
|
||||
* 传递无gc而且无精度损失
|
||||
* lua53下使用原生64位支持
|
||||
* 可以和number运算
|
||||
* 以java的方式支持无符号64位整数
|
||||
* table的自动转换到C#复杂类型
|
||||
* obj.complexField = {a = 1, b = {c = 1}},obj是一个C#对象,complexField是两层嵌套的struct或者class
|
||||
* obj.complexField = {a = 1, b = {c = 1}},obj是一个C#对象,complexField是两层嵌套的struct或者class
|
||||
* typeof
|
||||
* 对应C#的typeof操作符,返回Type对象
|
||||
* 对应C#的typeof操作符,返回Type对象
|
||||
* lua侧直接clone
|
||||
* decimal
|
||||
* 传递无gc而且无精度损失
|
||||
* 传递无gc而且无精度损失
|
||||
|
||||
## C#调用Lua
|
||||
|
||||
* 调用Lua函数
|
||||
* 以delegate方式调用Lua函数
|
||||
* 以LuaFunction调用lua函数
|
||||
* 以delegate方式调用Lua函数
|
||||
* 以LuaFunction调用lua函数
|
||||
* 访问Lua的table
|
||||
* LuaTable的泛化Get/Set接口,调用无gc,可指明Key,Value的类型
|
||||
* 用标注了CSharpCallLua的interface访问
|
||||
* 值拷贝到struct,class
|
||||
* LuaTable的泛化Get/Set接口,调用无gc,可指明Key,Value的类型
|
||||
* 用标注了CSharpCallLua的interface访问
|
||||
* 值拷贝到struct,class
|
||||
|
||||
## Lua虚拟机
|
||||
|
||||
@ -132,8 +132,8 @@
|
||||
## 工具链
|
||||
|
||||
* Lua Profiler
|
||||
* 可根据函数调用总时长,平均每次调用时长,调用次数排序
|
||||
* 显示lua函数名及其所在文件的名字及行号
|
||||
* 如果C#函数,会显示这个是C#函数
|
||||
* 可根据函数调用总时长,平均每次调用时长,调用次数排序
|
||||
* 显示lua函数名及其所在文件的名字及行号
|
||||
* 如果C#函数,会显示这个是C#函数
|
||||
* 支持真机调试
|
||||
|
||||
|
@ -1,32 +1,37 @@
|
||||
## 简介
|
||||
|
||||
热补丁允许你使用 xLua 的代码逻辑, 替换掉原有的 C# 程序逻辑, 以实现热补丁.
|
||||
|
||||
## 使用方式
|
||||
|
||||
1、打开该特性
|
||||
1. 打开该特性
|
||||
|
||||
添加HOTFIX_ENABLE宏,(在Unity3D的File->Build Setting->Scripting Define Symbols下添加)。编辑器、各手机平台这个宏要分别设置!如果是自动化打包,要注意在代码里头用API设置的宏是不生效的,需要在编辑器设置。
|
||||
添加 `HOTFIX_ENABLE` 宏,(在 Unity3D 的 "File->Build Setting->Scripting Define Symbols" 下添加)。编辑器、各手机平台这个宏要分别设置!如果是自动化打包,要注意在代码里头用 API 设置的宏是不生效的,需要在编辑器设置。
|
||||
|
||||
(建议平时开发业务代码不打开HOTFIX_ENABLE,只在build手机版本或者要在编译器下开发补丁时打开HOTFIX_ENABLE)
|
||||
(建议平时开发业务代码不打开 `HOTFIX_ENABLE`,只在构建手机版本或者要在编译器下开发补丁时打开 `HOTFIX_ENABLE`)
|
||||
|
||||
2、执行XLua/Generate Code菜单。
|
||||
2. 在菜单中找到 "XLua/Generate Code" 按钮并单击。
|
||||
|
||||
3、注入,构建手机包这个步骤会在构建时自动进行,编辑器下开发补丁需要手动执行"XLua/Hotfix Inject In Editor"菜单。打印“hotfix inject finish!”或者“had injected!”才算成功,否则会打印错误信息。
|
||||
3. 注入,构建手机包这个步骤会在构建时自动进行,编辑器下开发补丁需要手动执行 "XLua/Hotfix Inject In Editor" 菜单。打印 “hotfix inject finish!” 或者 “had injected!” 才算成功,否则会打印错误信息。
|
||||
|
||||
如果已经打印了“hotfix inject finish!”或者“had injected!”,执行xlua.hotfix仍然报类似“xlua.access, no field __Hitfix0_Update”的错误,要么是该类没配置到Hotfix列表,要么是注入成功后,又触发了编译,覆盖了注入结果。
|
||||
如果已经打印了 “hotfix inject finish!” 或者 “had injected!”,执行 `xlua.hotfix` 仍然报类似 “xlua.access, no field __Hitfix0_Update” 的错误,要么是该类没配置到 Hotfix 列表,要么是注入成功后,又触发了编译,覆盖了注入结果。
|
||||
|
||||
## 约束
|
||||
## 局限性
|
||||
|
||||
不支持静态构造函数。
|
||||
|
||||
目前只支持Assets下代码的热补丁,不支持引擎,c#系统库的热补丁。
|
||||
目前只支持 Assets 下代码的热补丁,不支持引擎,C# 系统库的热补丁。
|
||||
|
||||
## API
|
||||
xlua.hotfix(class, [method_name], fix)
|
||||
|
||||
`xlua.hotfix(class, [method_name], fix)`
|
||||
|
||||
* 描述 : 注入lua补丁
|
||||
* class : C#类,两种表示方法,CS.Namespace.TypeName或者字符串方式"Namespace.TypeName",字符串格式和C#的Type.GetType要求一致,如果是内嵌类型(Nested Type)是非Public类型的话,只能用字符串方式表示"Namespace.TypeName+NestedTypeName";
|
||||
* method_name : 方法名,可选;
|
||||
* fix : 如果传了method_name,fix将会是一个function,否则通过table提供一组函数。table的组织按key是method_name,value是function的方式。
|
||||
|
||||
base(csobj)
|
||||
`base(csobj)`
|
||||
|
||||
* 描述 : 子类override函数通过base调用父类实现。
|
||||
* csobj : 对象
|
||||
@ -41,7 +46,7 @@ xlua.hotfix(CS.BaseTest, 'Foo', function(self, p)
|
||||
end)
|
||||
```
|
||||
|
||||
util.hotfix_ex(class, method_name, fix)
|
||||
`util.hotfix_ex(class, method_name, fix)`
|
||||
|
||||
* 描述 : xlua.hotfix的增强版本,可以在fix函数里头执行原来的函数,缺点是fix的执行会略慢。
|
||||
* method_name : 方法名;
|
||||
@ -53,9 +58,13 @@ util.hotfix_ex(class, method_name, fix)
|
||||
|
||||
方式一:直接在类里头打Hotfix标签(不建议,示例只是为了方便演示采取这种方式);
|
||||
|
||||
方式二:在一个static类的static字段或者属性里头配置一个列表。属性可以用于实现的比较复杂的配置,比如根据Namespace做白名单。
|
||||
!!注意,方式一在高版本 Unity 不支持
|
||||
|
||||
~~~csharp
|
||||
方式二:在一个静态类的静态字段或者属性里头配置一个列表。属性可以用于实现的比较复杂的配置,比如根据命名空间做白名单。
|
||||
|
||||
!!注意,高版本 Unity 需要把配置文件放 Editor 目录下
|
||||
|
||||
```csharp
|
||||
//如果涉及到Assembly-CSharp.dll之外的其它dll,如下代码需要放到Editor目录
|
||||
public static class HotfixCfg
|
||||
{
|
||||
@ -77,7 +86,7 @@ public static class HotfixCfg
|
||||
}
|
||||
}
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
## Hotfix Flag
|
||||
|
||||
@ -85,37 +94,37 @@ Hotfix标签可以设置一些标志位对生成代码及插桩定制化
|
||||
|
||||
* Stateless、Stateful
|
||||
|
||||
遗留设置,Stateful方式在新版本已经删除,因为这种方式可以用xlua.util.state接口达到类似的效果,该接口的使用可以看下HotfixTest2.cs里的示例代码。
|
||||
遗留设置,`Stateful` 方式在新版本已经删除,因为这种方式可以用 `xlua.util.state` 接口达到类似的效果,该接口的使用可以看下`HotfixTest2.cs` 里的示例代码。
|
||||
|
||||
由于没Stateful,默认就是Stateless,所以也没必要设置该标志位。
|
||||
由于没 `Stateful`,默认就是 `Stateless`,所以也没必要设置该标志位。
|
||||
|
||||
* ValueTypeBoxing
|
||||
|
||||
值类型的适配delegate会收敛到object,好处是代码量更少,不好的是值类型会产生boxing及gc,适用于对text段敏感的业务。
|
||||
值类型的适配delegate会收敛到object,好处是代码量更少,不好的是值类型会产生boxing及gc,适用于对text段敏感的业务。
|
||||
|
||||
* IgnoreProperty
|
||||
|
||||
不对属性注入及生成适配代码,一般而言,大多数属性的实现都很简单,出错几率比较小,建议不注入。
|
||||
不对属性注入及生成适配代码,一般而言,大多数属性的实现都很简单,出错几率比较小,建议不注入。
|
||||
|
||||
* IgnoreNotPublic
|
||||
|
||||
不对非public的方法注入及生成适配代码。除了像MonoBehaviour那种会被反射调用的私有方法必须得注入,其它仅被本类调用的非public方法可以不注入,只不过修复时会工作量稍大,所有引用到这个函数的public方法都要重写。
|
||||
不对非public的方法注入及生成适配代码。除了像MonoBehaviour那种会被反射调用的私有方法必须得注入,其它仅被本类调用的非public方法可以不注入,只不过修复时会工作量稍大,所有引用到这个函数的public方法都要重写。
|
||||
|
||||
* Inline
|
||||
|
||||
不生成适配delegate,直接在函数体注入处理代码。
|
||||
不生成适配 delegate,直接在函数体注入处理代码。
|
||||
|
||||
* IntKey
|
||||
|
||||
不生成静态字段,而是把所有注入点放到一个数组集中管理。
|
||||
不生成静态字段,而是把所有注入点放到一个数组集中管理。
|
||||
|
||||
好处:对text段影响小。
|
||||
好处:对 text 段影响小。
|
||||
|
||||
坏处:使用不像默认方式那么方便,需要通过id来指明hotfix哪个函数,而这个id是代码注入工具时分配的,函数到id的映射会保存在Gen/Resources/hotfix_id_map.lua.txt,并且自动加时间戳备份到hotfix_id_map.lua.txt同级目录,发布手机版本后请妥善保存该文件。
|
||||
坏处:使用不像默认方式那么方便,需要通过id来指明hotfix哪个函数,而这个id是代码注入工具时分配的,函数到id的映射会保存在 `Gen/Resources/hotfix_id_map.lua.txt`,并且自动加时间戳备份到 `hotfix_id_map.lua.txt` 同级目录,发布手机版本后请妥善保存该文件。
|
||||
|
||||
该文件的格式大概如下(注意:该文件仅IntKey模式使用,当你没类型指定IntKey模式注入,该文件只返回个空表):
|
||||
该文件的格式大概如下(注意:该文件仅IntKey模式使用,当你没类型指定IntKey模式注入,该文件只返回个空表):
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
return {
|
||||
["HotfixTest"] = {
|
||||
[".ctor"] = {
|
||||
@ -138,19 +147,19 @@ return {
|
||||
},
|
||||
},
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
想要替换HotfixTest的Update函数,你得
|
||||
想要替换 `HotfixTest` 的 `Update` 函数,你得
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
CS.XLua.HotfixDelegateBridge.Set(7, func)
|
||||
~~~
|
||||
```
|
||||
|
||||
如果是重载函数,将会一个函数名对应多个id,比如上面的Add函数。
|
||||
如果是重载函数,将会一个函数名对应多个 id,比如上面的 `Add` 函数。
|
||||
|
||||
能不能自动化一些呢?可以,xlua.util提供了auto_id_map函数,执行一次后你就可以像以前那样直接用类,方法名去指明修补的函数。
|
||||
能不能自动化一些呢?可以,`xlua.util` 提供了 `auto_id_map` 函数,执行一次后你就可以像以前那样直接用类,方法名去指明修补的函数。
|
||||
|
||||
~~~lua
|
||||
```lua
|
||||
(require 'xlua.util').auto_id_map()
|
||||
xlua.hotfix(CS.HotfixTest, 'Update', function(self)
|
||||
self.tick = self.tick + 1
|
||||
@ -158,25 +167,24 @@ xlua.hotfix(CS.HotfixTest, 'Update', function(self)
|
||||
print('<<<<<<<<Update in lua, tick = ' .. self.tick)
|
||||
end
|
||||
end)
|
||||
~~~
|
||||
|
||||
前提是hotfix_id_map.lua.txt放到可以通过require 'hotfix_id_map'引用到的地方。
|
||||
```
|
||||
|
||||
前提是 `hotfix_id_map.lua.txt` 放到可以通过 `require 'hotfix_id_map'` 引用到的地方。
|
||||
|
||||
## 使用建议
|
||||
|
||||
* 对所有较大可能变动的类型加上Hotfix标识;
|
||||
* 建议用反射找出所有函数参数、字段、属性、事件涉及的delegate类型,标注CSharpCallLua;
|
||||
* 业务代码、引擎API、系统API,需要在Lua补丁里头高性能访问的类型,加上LuaCallCSharp;
|
||||
* 引擎API、系统API可能被代码剪裁调(C#无引用的地方都会被剪裁),如果觉得可能会新增C#代码之外的API调用,这些API所在的类型要么加LuaCallCSharp,要么加ReflectionUse;
|
||||
* 对所有较大可能变动的类型加上 `Hotfix` 标识;
|
||||
* 建议用反射找出所有函数参数、字段、属性、事件涉及的 delegate 类型,标注 `CSharpCallLua`;
|
||||
* 业务代码、引擎 API、系统 API,需要在 Lua 补丁里头高性能访问的类型,加上 `LuaCallCSharp`;
|
||||
* 引擎 API、系统 API 可能被代码剪裁调(C#无引用的地方都会被剪裁),如果觉得可能会新增 C# 代码之外的 API 调用,这些 API 所在的类型要么加 `LuaCallCSharp`,要么加 `ReflectionUse`;
|
||||
|
||||
## 打补丁
|
||||
|
||||
xlua可以用lua函数替换C#的构造函数,函数,属性,事件的替换。lua实现都是函数,比如属性对于一个getter函数和一个setter函数,事件对应一个add函数和一个remove函数。
|
||||
xlua可以用lua函数替换 C# 的构造函数,函数,属性,事件的替换。lua实现都是函数,比如属性对于一个 getter 函数和一个 setter 函数,事件对应一个 `add` 函数和一个 `remove` 函数。
|
||||
|
||||
* 函数
|
||||
|
||||
method_name传函数名,支持重载,不同重载都是转发到同一个lua函数。
|
||||
`method_name` 传函数名,支持重载,不同重载都是转发到同一个 lua 函数。
|
||||
|
||||
比如:
|
||||
|
||||
@ -207,41 +215,41 @@ end)
|
||||
|
||||
```
|
||||
|
||||
静态函数和成员函数的区别是,成员函数会加一个self参数,这个self在Stateless方式下是C#对象本身(对应C#的this)
|
||||
静态函数和成员函数的区别是,成员函数会加一个 self 参数,这个 self 在 Stateless 方式下是 C# 对象本身(对应 C# 的 this)
|
||||
|
||||
普通参数对于lua的参数,ref参数对应lua的一个参数和一个返回值,out参数对于lua的一个返回值。
|
||||
普通参数对于 lua 的参数,ref 参数对应 lua 的一个参数和一个返回值,out参数对于lua的一个返回值。
|
||||
|
||||
泛化函数的打补丁规则和普通函数一样。
|
||||
|
||||
* 构造函数
|
||||
|
||||
构造函数对应的method_name是".ctor"。
|
||||
构造函数对应的 `method_name` 是 ".ctor"。
|
||||
|
||||
和普通函数不一样的是,构造函数的热补丁并不是替换,而是执行原有逻辑后调用lua。
|
||||
|
||||
* 属性
|
||||
|
||||
对于名为“AProp”的属性,会对应一个getter,method_name等于get_AProp,setter的method_name等于set_AProp。
|
||||
对于名为 “AProp” 的属性,会对应一个 getter,`method_name` 等于 `get_AProp`,setter 的 `method_name` 等于 `set_AProp`。
|
||||
|
||||
* []操作符
|
||||
|
||||
赋值对应set_Item,取值对应get_Item。第一个参数是self,赋值后面跟key,value,取值只有key参数,返回值是取出的值。
|
||||
赋值对应 `set_Item`,取值对应 `get_Item`。第一个参数是 self,赋值后面跟 key,value,取值只有 key 参数,返回值是取出的值。
|
||||
|
||||
* 其它操作符
|
||||
|
||||
C#的操作符都有一套内部表示,比如+号的操作符函数名是op_Addition(其它操作符的内部表示可以去请参照相关资料),覆盖这函数就覆盖了C#的+号操作符。
|
||||
C#的操作符都有一套内部表示,比如 `+` 号的操作符函数名是 `op_Addition`(其它操作符的内部表示可以去请参照相关资料),覆盖这函数就覆盖了 C# 的 `+` 号操作符。
|
||||
|
||||
* 事件
|
||||
|
||||
比如对于事件“AEvent”,+=操作符是add_AEvent,-=对应的是remove_AEvent。这两个函数均是第一个参数是self,第二个参数是操作符后面跟的delegate。
|
||||
比如对于事件“AEvent”,+= 操作符是 add_AEvent,-=对应的是 remove_AEvent。这两个函数均是第一个参数是self,第二个参数是操作符后面跟的delegate。
|
||||
|
||||
通过xlua.private_accessible(版本号大于2.1.11不需要调用xlua.private_accessible)来直接访问事件对应的私有delegate的直接访问后,可以通过对象的"&事件名"字段直接触发事件,例如self\['&MyEvent'\](),其中MyEvent是事件名。
|
||||
通过 `xlua.private_accessible`(版本号大于2.1.11不需要调用 `xlua.private_accessible`)来直接访问事件对应的私有 delegate 的直接访问后,可以通过对象的"&事件名"字段直接触发事件,例如 `self['&MyEvent']()`,其中MyEvent是事件名。
|
||||
|
||||
* 析构函数
|
||||
|
||||
method_name是"Finalize",传一个self参数。
|
||||
method_name 是 "Finalize",传一个 self 参数。
|
||||
|
||||
和普通函数不一样的是,析构函数的热补丁并不是替换,而是开头调用lua函数后继续原有逻辑。
|
||||
和普通函数不一样的是,析构函数的热补丁并不是替换,而是开头调用 lua 函数后继续原有逻辑。
|
||||
|
||||
* 泛化类型
|
||||
|
||||
@ -253,10 +261,9 @@ public class GenericClass<T>
|
||||
}
|
||||
```
|
||||
|
||||
你只能对GenericClass\<double\>,GenericClass\<int\>这些类,而不是对GenericClass打补丁。
|
||||
你只能对 `GenericClass<double>`,`GenericClass<int>` 这些类,而不是对 `GenericClass` 打补丁。
|
||||
|
||||
|
||||
对GenericClass<double>打补丁的实例如下:
|
||||
对 `GenericClass<double>` 打补丁的实例如下:
|
||||
|
||||
```csharp
|
||||
luaenv.DoString(@"
|
||||
@ -277,9 +284,9 @@ luaenv.DoString(@"
|
||||
|
||||
* Unity协程
|
||||
|
||||
通过util.cs_generator可以用一个function模拟一个IEnumerator,在里头用coroutine.yield,就类似C#里头的yield return。比如下面的C#代码和对应的hotfix代码是等同效果的
|
||||
通过 `util.cs_generator` 可以用一个 function 模拟一个 `IEnumerator`,在里头用 `coroutine.yield`,就类似 C# 里头的 yield return。比如下面的 C# 代码和对应的 hotfix 代码是等同效果的
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
[XLua.Hotfix]
|
||||
public class HotFixSubClass : MonoBehaviour {
|
||||
IEnumerator Start()
|
||||
@ -291,9 +298,9 @@ public class HotFixSubClass : MonoBehaviour {
|
||||
}
|
||||
}
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
~~~csharp
|
||||
```csharp
|
||||
luaenv.DoString(@"
|
||||
local util = require 'xlua.util'
|
||||
xlua.hotfix(CS.HotFixSubClass,{
|
||||
@ -307,11 +314,11 @@ luaenv.DoString(@"
|
||||
end;
|
||||
})
|
||||
");
|
||||
~~~
|
||||
```
|
||||
|
||||
* 整个类
|
||||
|
||||
如果要替换整个类,不需要一次次的调用xlua.hotfix去替换,可以整个一次完成。只要给一个table,按method_name = function组织即可
|
||||
如果要替换整个类,不需要一次次的调用 `xlua.hotfix` 去替换,可以整个一次完成。只要给一个 table,按 `method_name = function` 组织即可
|
||||
|
||||
```lua
|
||||
|
||||
@ -365,4 +372,3 @@ xlua.hotfix(CS.StatefullTest, {
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
|
@ -1,85 +1,55 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b9f4e2e38c36db40bc5bdfe20038d94
|
||||
timeCreated: 1481715979
|
||||
licenseType: Pro
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
enableMipMap: 1
|
||||
linearTexture: 0
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapU: -1
|
||||
wrapV: -1
|
||||
wrapW: -1
|
||||
wrapMode: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
allowsAlphaSplitting: 0
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 1
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 1
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
textureType: -1
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
|
BIN
Assets/XLua/Doc/xLua.png
Normal file
BIN
Assets/XLua/Doc/xLua.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 28 KiB |
56
Assets/XLua/Doc/xLua.png.meta
Normal file
56
Assets/XLua/Doc/xLua.png.meta
Normal file
@ -0,0 +1,56 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2926ca0864130e40b99cbe18d0fc395
|
||||
timeCreated: 1481699971
|
||||
licenseType: Pro
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
linearTexture: 0
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapMode: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
allowsAlphaSplitting: 0
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 0
|
||||
textureType: -1
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user