热门标签 | 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


推荐阅读
  • 解决.net项目中未注册“microsoft.ACE.oledb.12.0”提供程序的方法
    在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报错“未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序”。本文提供了解决这个问题的方法,包括错误描述和代码示例。通过注册提供程序和修改连接字符串,可以成功读取excel文件信息。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • EPPlus绘制刻度线的方法及示例代码
    本文介绍了使用EPPlus绘制刻度线的方法,并提供了示例代码。通过ExcelPackage类和List对象,可以实现在Excel中绘制刻度线的功能。具体的方法和示例代码在文章中进行了详细的介绍和演示。 ... [详细]
  • 本文总结了使用不同方式生成 Dataframe 的方法,包括通过CSV文件、Excel文件、python dictionary、List of tuples和List of dictionary。同时介绍了一些注意事项,如使用绝对路径引入文件和安装xlrd包来读取Excel文件。 ... [详细]
  • Java如何导入和导出Excel文件的方法和步骤详解
    本文详细介绍了在SpringBoot中使用Java导入和导出Excel文件的方法和步骤,包括添加操作Excel的依赖、自定义注解等。文章还提供了示例代码,并将代码上传至GitHub供访问。 ... [详细]
  • Annotation的大材小用
    为什么80%的码农都做不了架构师?最近在开发一些通用的excel数据导入的功能,由于涉及到导入的模块很多,所以开发了一个比较通用的e ... [详细]
  • VBA操作Excel之设置单元格属性
    VBA操作Excel简介一、VBA读写Excel文件二、VBA设置单元格属性三、VBA弹出输入和输出窗口参考文档一、VBA读写Excel文件VBA简介及打开Excel文件方法见VB ... [详细]
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社区 版权所有