热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【游戏开发】手游开发中常用的Lua相关技术总结

metatableLua中metatable是一个普通的table,主要有以下几个功能:1.重载运算符2.为Lua函数库提供支持3.控制对table

metatable

Lua 中 metatable 是一个普通的 table,主要有以下几个功能:

1.重载运算符
2.为 Lua 函数库提供支持
3.控制对 table 的访问
4.实现OOP的继承

__index 元方法

这是 metatable 最常用的键。

当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。

如果__index包含一个表格,Lua会在表格中查找相应的键。

__newindex

__newindex 元方法用来对表更新。
当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。

Lua 协同程序

Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。
Unity中的协程是为了实现多线程效果而用,例如异步下载数据加载等。而Lua中的协程更像是某一个任务做到某一步挂起,然后去做另一件事,另一件事做完再回来做当前的任务。

排查 Lua 内存问题:方法1-快照

内存快照 - 计算Lua对象内存大小 - 储存快照

在这里插入图片描述
遍历可回收对象用sizeof计算,快照结果写入文件或输出到控制台。

常见泄漏:
1.C#代理
如果把Lua匿名函数注册给C#的代理,那么这个Lua匿名函数将不能正确地被LuaGC了
2.Lua的string是不可变值
用table.concat替换

排查 Lua 内存问题:方法2-弱引用表

用弱引用表来检查Lua是否存在泄漏,创建一个全局的弱引用table,使其key为弱引用,value用当前时间。
如果已被lua gc释放掉,则key为nil,当程序跑过释放对象的逻辑后,表中弱引用仍然存在的,视为内存泄漏。

优化Lua配表占用内存

1.对于Excel中的一列,出现次数最多的值认定为默认值,然后把它从Lua表中剔除掉,然后利用metatable机制实现全局默认值存储;
2.对于中文字符串,替换为一个唯一的id标识,写回到Lua表中,读取的时候加上相应的查找替换;
3.对于一些复杂的子表或着数组,做唯一化替换处理,替换后写回到原始数据中;

Lua table底层如何实现

Table包含两部分:数组(array)部分和哈希(hash)部分,数组部分保存整数键值(key)为1到n范围内的值(entry),n是一些独特的数值。其他的值(包括整数下标超出1到n范围的)保存在哈希部分。

重新哈希(rehash):第一步是决定新的数组部分和哈希部分的大小。所以Lua会遍历表中的所有值,对这些值进行计数和分类,然后选择一个小于数组部分大小的2的最大指数值,使数组的一半以上会被使用。哈希部分的大小就是大于剩下的值(不能放在数组部分的值)的数量的最小2的指数值。
第二步是realloc,realloc的实现方法是:先在该内存块后面检查是否有足够的空间进行扩容,如果可以,则在该内存块后面增加需要扩容的空间;否则,需要申请一块新的内存块进行扩容。

XLua增加第三方lua库

在CMakeLists.txt文件加入扩展

Lua 面向对象

属性 table
方法 function
继承 metatable
基类 - o = o or {}
派生类 - o = o or 基类:new(…)

Lua调用C#

1.CS.XXXXX
CS是一个全局的Table,CS.UnityEngine可以当做是在一个名为CS的Table表中查询名为UnityEngine的值。获取其值是通过CS的元方法__index来实现的。其逻辑代码在创建LuaEnv时候调用下面的代码,进行CS表的初始化。
DoString(init_xlua, “Init”);

2.Lua中获取C#类对应的Table表
XLua中有两种方式来实现Lua调用CS中的方法,一种是反射来调用,一种是生成适配的代码。

3.Xlua调用C#原理
XLua中有两种方式来实现Lua调用CS中的方法,一种是反射来调用,一种是生成适配的代码(在XLua中生成适配代码后会在Gen目录生成代码:注册成员方法(压入方法名和委托),注册类方法,注册回调)

C#调用Lua

创建Lua虚拟机 LuaEnv

1.直接写lua: luaenv.DoString(“XXX’”);
2.C#访问Lua中的全局基本数据类型 luaenv.Global.Get(“a”);
3.C#访问Lua特定类型 luaenv.Global.Get(“person”);

用C#加载Lua脚本文件
Lua mylua = new Lua();
mylua.DoFile(“lamlua.lua”); //存放在bin目录下

将C#中的函数/方法 写入到Lua脚本中

Lua lua = new Lua(); //创建一个lua解释器
Program program = new Program(); //声明一个对象
lua.RegisterFunction("LuaTest", program, program.GetType().GetMethod("Test"));public void Test()
{...
}

闭包

闭包(closure)是由一个函数和该函数会访问到的非局部变量(或者是upvalue)组成的,其中非局部变量(non-local variable)是指不是在局部作用范围内定义的一个变量,但同时又不是一个全局变量,主要应用在嵌套函数和匿名函数里,因此若一个闭包没有会访问的非局部变量,那么它就是通常说的函数。

闭包的应用:
1.作为高阶函数的参数,比如像table.sort函数的参数。
2.创建其他的函数的函数,即函数返回一个闭包。
3.闭包对于回调函数也非常有用。典型的例子就是界面上按钮的回调函数,这些函数代码逻辑可能是一模一样,只是回调函数参数不一样而已,即upvalue的值不一样而已。
4.创建一个安全的运行环境,即所谓的沙盒(sandbox)。当执行一些未受信任的代码时就需要一个安全的运行环境。比如要限制一个程序访问文件的话,只需要使用闭包来重定义函数io.open


推荐阅读
author-avatar
手机用户2702934324
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有