il2Cpp编译失败

最近发现在使用scriptDebug的选项的时候无法正常编译,在导出的工程里il2Cpp编译的时候报错,但是如果不开启scripteDebug的话,就完全正常,

后来经过查询发现我们的unity的版本使用的NDK是r19的版本,在这个版本上是有bug的,内容过大会无法编译报错,因为使用了Debug的脚本,所以会增加很多代码内容,所以会边编译失败,解决方案目前是先裁剪下代码吧,然后后续看看怎么优化削减相关的C#的脚本

https://forum.unity.com/threads/android-builds-failing-when-script-debugging-is-enabled.1027357/

Lua的#取长度的版本差异

之前一直用的是Lua5.1最近看源码的时候发现一个有趣的问题,在对一个table进行取长度的时候获取会得到不同的长度。

print(#{1,2, nil} = 2

print(#{1, nil, 2, nil})= 4

按照之前理解可能在最后一个数据为nil的情况下table的长度为3的,而不是4。所以这里存在误区,在lua5.1的版本上取长度操作是有个处理函数我大概看了下是一个二分的查找判断是否在某个位置上存在数据,然后循环遍历查找,


但是在我自己的电脑上因为采用的lua版本是5.4的版本,我并未复现了这个问题,然后看了下果然在5.4的版本和5.1的版本是有差异的

5.4的版本下

print(#{1, nil, 2, nil})= 3

一些基本的特效贴图优化

首先最基本的就是贴图必须要是整数倍

然后最大利用贴图内容,保证大小设置合理

高级的方案:

  1. 通过RGB通过来合并三张类似的贴图变为一张贴图,这个也是看别的人操作 https://www.bilibili.com/video/BV1Ef4y1Y72y
  2. 尽量使用shade进行染色,而不使用相关的多张贴图换不同的颜色
  3. 圆圈的利用率极低, 所以使用shader加上贴图渐变极坐标的方式通过直线合成一个圆圈,其实就是相当于自己画一个圆了

一些优化思路

首先打包出来的清单文件在进游戏加载格式字符串展开和解析都有一定的消耗,

并且List大小不是预设固定的是有消耗的,所以打算将清单文件构建改成scriptobject的脚本。

字符串做kv字典映射表格,减少堆内存展开分配。然后看是否可以转换策划配表中的路径,通过同样的映射表格进行转换。

另外bundle的列表做混淆避免明文列表

其次是最近看代码发现其中的luajit没有启用,虽然不清楚原因是什么,但是考虑下看看是否可以启用尝试看看。

Unity的AssetBundle构建Patch流程

之前项目中的patch更新是依赖于整个bundle的更新,但是由于颗粒度的问题,总是导致补丁包的大小不可控制,目前在考虑做一定的补丁优化工作。

首先之前的逻辑是按照小的版本更新,假设存在7.00.00版本,后续有资源或者代码更新,那么就重新构建一次7.00.01的版本,并且对两个版本之前的bundle的fingerPrint做比较拿出对应的差异文件,然后更新打热更zip。但是这个文件更新的颗粒度是AssetBundle的级别,所以这个时候如果更新可能会出现一个1M的bundle,实际上只修改里面的一个小的5K的图片,那么就导致资源的冗余更新,所以一直在考虑做小的补丁的patch流程。

当前的考虑是利用bsdiff工具对版本进行热更,目前对相关的代码进行测试,主要发现的问题在于BSDiff的代码需要将之前老的bundle都拿出来才能对old bundle进行patch流程,但是由于发布的时候apk内部的bundle是无法通过C#直接load出来的。

目前的方案有两种

  1. 通过原生层拿到对应的文件字节流数据,然后对应的进行apply到persist目录下
  2. 将apk包分离为两种模式,一种是底包,一种是热更包,热更包始终是不进首包的目录,这种方案符合我们当前的逻辑需求

所以考虑下,实现两种方案逻辑

各种热更方案总结

目前主流的两种一个是ILRuntime和Huatuo。

目前大概跑了下两种方案,ILRuntime其实看起来就是用C#的特性,重新载入相关的DLL,这个其实直接在安卓上本身就可以跑,但是由于在iOS上对读写权限的控制,导致无法直接进行相关的DLL的更新和覆盖,所以这个时候依赖第三方工作自己做的DLL的加载和执行的能力。

实际上来说如果没有iOS的权限控制,就直接可以加载DLL, 这里的ILRuntime看下来执行编译器的操作,将对应的C#的字节码转换成对应的指令集进行操作,也就是可以正常运行一般的C#代码,但是这个时候如果想用到unity相关的api集成相关的类,就要进行反射处理。另外这个地方的重点是虽然执行了相关的字节码,因为是JIT的所以会有两个虚拟机,那么这里为了进一步优化性能,会提前直接对相关函数进行绑定。

而huatuo实际上是做了IL2CPP的修改,直接把IL2CPP的执行C#逻辑进行处理,并且在代码中做了转换,使用原本的IL2CPP VM做转换,在原本的虚拟机执行新的代码,并且保证相关的数据内存对象只有一份,没有什么接口导出什么的。避免两个虚拟机直接来回穿梭。

lua的异常捕获和Debug调试函数

首先常规的pcall 和Xpcall 的一个最大的区别是Xpcall 是可以执行一个出错函数,也就是相当于执行一了一个try catch 的finally方法,并且Xpcall是可以保存相关的调用堆栈,这样的可以保证一些有效的信息执行或者出错保护之类,

其实简单类比的话,就是pcall 是try catch然后再catch中print相关的错误信息,但是Xpcall就是会额外执行一个传入的函数相当于一个finally里的操作。

基本常用的出错保护函数是debug.traceback函数,可以打印相关的调用堆栈信息来扩展出错消息。

debug.traceback可以打印调用堆栈信息

debug.debug 可以运行输入字符串,相当于进入一个交互模式,输出相关计算相关的表达式