lua table & python dictionary

本文探讨了在处理C++、Lua和Python混合技术栈时遇到的问题,特别是如何高效地处理和组合多个Lua表格数据。作者提出将静态数据结构提前生成并存储,以避免在游戏中动态生成消耗性能。解决方案涉及使用Python将多个Lua表格转换为单一表格,并介绍了slpp库在Python 2和3中的应用,以及自定义输出格式的实现。

遇到的问题

公司前端的技术栈是 C++ & lua & python, C++、lua做业务开发,python做工具。
lua特别好用的东西就是load, 将某些数据(一般是excel)转成lua的table存储,用的时候直接load进来。
但是,有些数据,并不是excel转过来的,通过多个excel来组成。

例如:
描述: 一个卡牌游戏,肯定有一张卡牌表,在表中我可以知道每张卡牌属于哪个职业。

Question: 在游戏中,我想知道某职业所有卡牌,怎么办呢?
我需要遍历这个卡牌表,然后把相应职业的卡牌筛选出来。
但是,这个方法随着卡牌库的增加,所花费的时间也不断增加,早晚会出事呀。
当然,可以通过各种人为规定,算法设计来加快速度。
可是,都没有根本去解决问题。
回过头来,可以发现,当我们有了这张卡牌表,我就可以知道某职业都有哪些牌。
这就是像卡牌表一样,不需要在游戏中动态去生成,直接可以本地存储静态的一个职业对应卡牌的表。
这样,即使生成这张表再慢,也不会消耗游戏运行中的时间和性能。




解决问题

分析

现在目标很明确了,我要把n个表,根据需求组合拼装成1个表。
麻烦的是,表的生成这些东西,我们都已经做成脚本,交给策划生成了。
这个东西,肯定也需要交给策划进行。
不可能让策划打完表以后,程序再去执行一遍lua脚本。
(PS:这种东西一定要规避掉,一定要学会自动化,工具化。不要把我们的时间浪费在这些可以自动化、工具化的东西上。)

所以,目前状况是:
语言:python
输入:n张lua表
输出:1张lua表
逻辑:一系列插入、查找、遍历等

中间的逻辑就不用多说了,python的dict 和 lua的table用法也挺像的。
主要处理两个问题:

  1. 将lua table 转换成 python dict
  2. 将python dict 转换成 lua table


大概思路

在动手前,肯定要看有没有好的现成的轮子。重复造轮子还是不要了吧,不一定造的比人家好呢。
经过一番查找,发现了 slpp[ https://github.com/SirAnthony/slpp ]
它可以实现lua table 和 python dict之间的转换。
但是,它是python2.x版本。
然后,在推送请求上看到,有人已经做了python3.x版本。 slpp-23[ https://github.com/IlyaSkriblovsky/slpp-23 ]


一些细节

大概的方向差不多了,剩下的就是符合我所需要的格式。
因为,我的文件格式是这样的:

        local xx_xx = {
            [1] = {
                ...
            },
            [2] = {
                ...
            },
            ...
        }
        return xx_xx

对于输入要求,还简单一些:

        """
            描述:
                将lua的table转成python的dict

            参数:
                table_file_name - string
                    文件名(需要加后缀)

            返回:
                dict格式的table
        """
        def convertLuaTableToPythonDict(table_file_name):
            content = ""
            with open(table_file_name, 'r', encoding='utf-8') as f:
                content = f.read()

            content = content[content.find('{') : content.rfind('}')+
1、水面波浪起伏的效果是如何实现的?波光粼粼的效果又是如何实现的?2、静态合批与动态合批的原理是什么?有什么限制条件?为什么?对CPU和GPU产生的影响分别是什么?3、一个正方体多少个顶点和三角形,为什么?如何合并顶点?4、什么是DrawCall,如何减少DrawCall?5、资源生命周期如何管理?如何加载与释放资源?资源打包颗粒是怎么设计的?资源压缩格式是什么?6、一个相机中如何做分层渲染?底层原理是什么?7、渲染管线的流程,后处理泛光效果如何实现?8、项目中热更新流程是怎样的?热更包颗粒如何设计?资源如何加密?协议如何加密?9、如何实现物体被墙遮蔽后显示轮廓的效果?shader的pass是什么东西?10、TCP连接的流程是怎样的?11、项目中的打包工具做了什么事情?如何做自动化打包?12、lua的闭包是什么?闭包产生的内存泄露如何解决?13、A*寻路算法的原理是什么?还知道其他寻路算法吗?14、求一个大型排行榜的Top100用什么算法,过程是怎么样的?15、luatable的底层实现原理是什么?为什么这么设计?16、如果让你自己实现C#字典,你如何设计?17、3D转2D碰撞检测的实现过程,使用什么算法进行检测?18、讲讲你对URP的了解。19、讲讲你对ECS的了解。20、lua与C#或C语言相互调用的底层实现原理是什么?21、代码安全具体做了什么内容?22、性能优化做了什么内容?
最新发布
08-09
### 游戏开发中的关键技术问题汇总 #### 水面波浪与波光效果实现原理 水面波浪的模拟可以通过多种方法实现,其中一种常见的方法是使用顶点动画来模拟波浪运动。在Unity中,可以利用Shader编写顶点函数,对顶点的位置进行动态调整,从而产生波浪效果。波浪的形状可以通过正弦波叠加来实现,即通过多个不同频率和振幅的正弦波组合,形成更加自然的波浪形态。波光效果则可以通过动态调整水面的反射和折射属性来实现,例如使用法线贴图来模拟水面的微小扰动,进而影响光照的反射方向,产生闪烁的波光效果[^4]。 #### 静态与动态合批原理及性能影响 静态合批是指将多个静态网格合并成一个大的网格,以便在一次DrawCall中渲染,从而减少CPU向GPU发送渲染命令的次数。这种方法适用于不发生变化的物体,如建筑物、地形等。动态合批则是针对移动的物体,通过在每一帧将多个小的动态网格合并成一个大的网格来减少DrawCall的数量。尽管动态合批可以提高渲染效率,但它会增加每帧的CPU计算负担,因为需要不断地重新合并网格。因此,在使用动态合批时需要权衡其带来的性能增益与额外的CPU开销。 #### 正方体顶点与三角形数量及顶点合并方法 一个标准的正方体由8个顶点和6个面组成,每个面由2个三角形构成,因此总共有12个三角形。如果直接按照每个面单独定义顶点的方式构建正方体,则每个面的4个顶点会被重复定义,导致顶点总数为24个。然而,通过顶点索引技术,可以共享顶点数据,从而减少顶点数量至8个。顶点合并方法通常涉及查找并合并具有相同位置、法线、纹理坐标等属性的顶点,以减少模型的数据冗余。 #### DrawCall定义与优化策略 DrawCall指的是CPU向GPU发送的一条渲染指令,指示GPU渲染一个特定的几何对象。过多的DrawCall会导致CPU成为瓶颈,尤其是在移动设备上。为了优化DrawCall,可以采取以下几种策略:静态和动态合批、使用纹理图集减少材质切换、合理使用LOD(Level of Detail)技术、以及优化渲染顺序以减少状态切换。 #### 资源生命周期管理与打包压缩机制 资源生命周期管理涉及资源的加载、使用、卸载等过程。有效的资源管理可以确保游戏运行时内存占用保持在合理范围内。资源打包压缩机制通常包括将资源打包成AssetBundle或Scene文件,并采用压缩算法(如LZMA或LZ4)来减小包体大小,加快加载速度。此外,还需要考虑资源的热更新机制,以便在不重新发布整个游戏的情况下更新资源。 #### 相机分层渲染原理 相机分层渲染是一种将场景中的物体按照层次划分,并由不同的相机负责渲染的技术。这种技术可以用于实现UI覆盖、特效渲染等场景。每个相机可以设置不同的Culling Mask,指定它应该渲染哪些层的对象。通过这种方式,可以灵活控制不同层对象的渲染顺序和方式,提高渲染效率。 #### 渲染管线流程与后处理泛光实现 Unity的渲染管线流程包括摄像机设置、剔除、阴影投射、前向或延迟渲染等多个阶段。后处理泛光(Bloom)效果是通过提取画面中亮度较高的部分,对其进行模糊处理,然后将处理后的图像叠加回原图来实现的。这一过程通常涉及多个渲染阶段,包括亮度阈值提取、高斯模糊、以及最终的混合操作。 #### 热更新流程与加密机制 热更新是指在不停止游戏的情况下更新游戏内容的技术。热更新流程通常包括版本检测、差异文件下载、解压安装、以及重启游戏客户端等步骤。为了保护更新内容的安全性,通常会对更新包进行加密处理,常见的加密机制包括对称加密(如AES)和非对称加密(如RSA)。 #### 遮挡轮廓效果与Shader Pass概念 遮挡轮廓效果通常用于突出显示被其他物体遮挡的对象边缘。实现这种效果的一种方法是在Shader中使用两个Pass:第一个Pass用于绘制物体的背面,并稍微放大物体,使其边缘超出实际物体边界;第二个Pass用于正常绘制物体。通过这种方式,可以形成一种边缘发光的效果。Shader中的Pass概念指的是渲染过程中的一次独立渲染操作,每个Pass可以有不同的光照模型、材质属性等设置。 #### TCP连接流程 TCP连接的建立遵循三次握手协议,即客户端发送SYN报文请求建立连接,服务器回应SYN-ACK报文,最后客户端发送ACK确认报文。连接的关闭则遵循四次挥手协议,即一方发送FIN报文表示不再发送数据,另一方回应ACK报文确认接收,待数据传输完毕后,另一方也发送FIN报文,最初发送方回应ACK报文确认关闭连接。 #### 自动化打包工具设计 自动化打包工具的设计通常包括版本控制、依赖管理、构建脚本、打包配置等模块。通过编写脚本语言(如Python或Shell脚本),可以自动化执行资源编译、代码编译、资源打包、版本号更新等任务,从而提高开发效率。 #### Lua闭包与内存泄漏 Lua中的闭包是由函数和与其相关的非局部变量组成的函数值。闭包可以访问其创建时所在环境中的变量,即使这些变量在其外部不可见。内存泄漏是指程序在申请内存后,未能释放不再使用的内存。在Lua中,由于垃圾回收机制的存在,内存泄漏的可能性较低,但仍需注意避免不必要的全局变量引用,以免阻碍垃圾回收器的工作。 #### A*算法与其他寻路算法 A*算法是一种启发式搜索算法,广泛应用于游戏中的寻路问题。它结合了Dijkstra算法的成本评估和启发式估计,能够在大多数情况下找到最短路径。除了A*算法外,还有其他寻路算法,如Dijkstra算法、广度优先搜索(BFS)、深度优先搜索(DFS)等,每种算法都有其适用场景。 #### Top100排行榜算法 实现Top100排行榜的一种常见方法是使用优先队列(堆)。每当有新的分数插入时,维护一个最大堆,保持堆的大小不超过100,这样堆顶元素即为当前排行榜上的最低分数。当需要查询排行榜时,可以直接取出堆中的所有元素。 #### Lua Table底层实现 Lua中的Table是一种关联数组,可以使用任意类型的值作为键。Table的底层实现采用哈希表和数组的混合结构。对于连续的整数键,Lua会使用数组部分存储;而对于其他类型的键,则使用哈希表部分存储。 #### C#字典设计思路 C#中的字典(Dictionary<TKey, TValue>)基于哈希表实现,提供了快速的查找、插入和删除操作。字典内部维护一个数组,数组中的每个元素是一个桶(Bucket),桶中存放的是键值对的链表。当发生哈希冲突时,通过链地址法解决。 #### 3D转2D碰撞检测算法 3D转2D碰撞检测通常涉及将3D空间中的物体投影到2D平面上,然后使用2D碰撞检测算法判断是否发生碰撞。常用的2D碰撞检测算法包括轴对齐包围盒(AABB)、分离轴定理(SAT)等。 #### URP与ECS架构理解 URP(Universal Render Pipeline)是Unity提供的一种轻量级渲染管线,支持跨平台开发。ECS(Entity Component System)是一种面向数据的设计模式,适用于大规模数据处理和并行计算。在Unity中,ECS与Job System、Burst编译器相结合,可以显著提升性能。 #### Lua与C#交互机制 Lua与C#之间的交互通常通过中间层实现,该中间层负责处理类型转换、函数调用等任务。在Unity中,可以使用tolua、ulua等插件来简化Lua与C#之间的交互过程。 #### 代码安全机制 代码安全机制主要包括代码混淆、加密、签名验证等措施。代码混淆通过改变代码结构,使其难以被逆向工程;加密则用于保护敏感数据;签名验证确保代码来源的合法性。 #### 性能优化实践 性能优化是一个持续的过程,涉及多个方面,包括但不限于:减少DrawCall、优化资源加载、合理使用多线程、减少内存分配、避免不必要的计算等。此外,还可以利用性能分析工具(如Unity Profiler)来定位性能瓶颈,并针对性地进行优化。 ```python def quick_sort(arr): if len(arr) <= 1: return arr else: # 选择基准值 pivot = arr[len(arr) // 2] # 分别存放比基准小和大的元素 left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] # 递归地对左右两边进行快排,并合并结果 return quick_sort(left) + middle + quick_sort(right) ``` ```csharp // 示例:C#字典的基本使用 Dictionary<string, int> scores = new Dictionary<string, int>(); scores.Add("Alice", 90); scores.Add("Bob", 85); int aliceScore = scores["Alice"]; ``` ```lua -- 示例:Lua表的基本操作 local playerScores = {} playerScores["Alice"] = 90 playerScores["Bob"] = 85 print(playerScores["Alice"]) ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值