1.xlua框架概述
为了实现热更新功能,xlua框架可以让c#和lua相互调用访问。 Lua 本身就是一种解释型语言,它的代码可以在运行时进行解析、编译和执行。 xlua 可以通过 C# 的反射机制,将 C# 类型与 Lua 进行绑定。即在运行时,Lua 可以直接访问 C# 类的方法、字段等,调用 Unity 引擎的各种 API。
2.lua 面向对象
lua面向对象三大特性
封装:利用table进行封装
继承:利用元表和__index模拟继承关系 设置子类的元表为父类,父类的__index为父类自己 当子类身上找不到对应属性和方法时 会查找元表的__index中的内容,也就是会查找父类中的内容 通过这种方式来模拟继承
多态:子类自己去实现带:的同名方法即可
3.pairs与ipairs 区别
pairs会遍历所有key,对于key的类型没有要求,遇到nil时可以跳过,不会影响后面的遍历,既可以遍历数组部分,又能遍历哈希部分。
ipairs只会从1开始,步进1,只能遍历数组部分, 中间不是数字的key忽略, 到第一个不连续的数字为止(不含),遍历时只能取key为整数值,遇到nil时终止遍历。
4. _index 与 _newindex的区别
__index 用于 读取 表中不存在的键。它可以是一个表或一个函数。当你访问一个表中不存在的字段时,Lua 会通过 __index 查找是否可以找到这个字段。
如果 __index 是一个表,Lua 会在该表中查找缺失的键。
如果 __index 是一个函数,Lua 会调用该函数,并传递表和缺失的键。
__newindex 用于 修改 表中不存在的或已存在的键的值。它在你尝试为表的一个不存在的字段赋值时触发。可以用来拦截或自定义对表中元素的修改。
如果__newindex是一个表,那么会把这个值赋值到newindex所指的表中(有这个索引就修改,没有就创建),不会修改自己。
如果__newindex是一个函数,那么会调用这个函数。
5. Table原理
其他会存在哈希表里面,
数组部分:从 1 开始做整数数字索引,如 {1, 2, 3} 或 {10, 20, 30}。;数组部分存储在 TValue *array 中,其长度信息存储在 int sizearray 中。
哈希部分:用于存储非整数索引或者稀疏数组的元素,如键值对 {key = value} 或 {["name"] = "Alice"}。 哈希表是通过一个开放寻址法去解决哈希冲数组部分会在内存分配时采用“指数增长”策略,而哈希表则会根据负载因子(即元素个数与表大小的比值)进行扩展。
每个 Table 结构,最多会由三块连续内存构成:
(1) 一个 table 结构
(2) 一块存放了连续整数索引的数组
(3) 一块大小为 2 的整数次幂的哈希表
所以table会将部分整形key作为下标放在数组中, 其余的整形key和其他类型的key都放在hash表中。
table中的hash表的实现结合了以上两种方法的一些特性:
查找和插入等同链地址法(拉链法)复杂度。
内存开销近似等同于开放定址法。
6.lua的GC算法
三色标记清除算法
1每个新对象都设置为白色
2初始化阶段 遍历 root节点中引用的对象,从白色变成灰色,放入到灰色节点列表。
3标记阶段 循环灰色链表中的未扫描的元素,取出一个对象置为黑色,遍历对象关联的所有其他对象 如果是白色 则标记为灰色,加入灰色链表
4回收阶段 遍历所有对象,如果为白色,没有被引用的对象执行回收。否则加入到对象链表中,等待下一轮gc
7.lua和c#的交互
C# 和 Lua 中的基本数据类型(如整型、浮点型、字符串等)之间有不同的表示方式。因此,需要一个映射机制来保证 C# 中的数据类型能正确地转换成 Lua 中的对应类型。而 C#与Lua进行交互主要通过虚拟栈实现,栈的索引分为正数与负数,若索引为正数,则1表示栈底,若果索引为负数,则-1表示栈顶。 C#调用Lua是:由 C# 先把数据或者请求放入栈中,由 Lua 去栈中取数据,然后返回数据对应的值到栈顶,再由栈顶返回 C#。
Lua 调 C# 也一样:先编写自己的 C模块,然后注册函数到 Lua 解释器中,然后由 Lua 去调用这个模块的函数。
8.闭包
闭包可以保存外部函数内的变量,可以根据外部函数内的变量来得到不同的结果,不会随着外部函数调用完而因为生命周期结束而被gc回收,当闭包执行完成后,仍可以保持当前的运行环境,执行结果依赖于该函数上一次的运行结果。但是由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,这样会比较消耗内存。
function add()
local x = 0
return function () x = x + 1
return x
end
end
add1 = add()
print(add1())
--1 print(add1())
--2 add2 = add()
常见于循环里面,某个方法持有变量的引用。如果想要不因为循环递增而修改变量数值,可以使用记录临时变量。