优化Flash中的3D模型加载

最近在做一个公司的Flash3D页游项目,遇到了这个问题,前前后后断断续续也优化了一段时间,觉得还是有必要记录一下一些优化的心得。

Flash中加载资源一个最大的问题在于难以使用另外的线程加载资源。诚然Flash有Worker线程,但Worker存在以下几个问题:
1. 使用Worker要求客户的FlashPlayer播放器版本不能过低。
2. 不同Worker之间传递数据手段非常少,缺乏共享内存。使用ByteArray共享数据的话需要先把数据序列化成AMF格式,无论序列化还是解析都是一个耗时的操作。
3. Worker实际上是另一个swf文件,增加程序复杂度。
4. 需要使用FlashBuilder4.7才能开发worker,而4.7一堆bug。

既然只能在渲染线程中加载和解析模型,那么我们就只能力求加载速度足够快。同时,作为页游,模型文件的体积也要足够小。

模型文件格式的选择

基于多种考虑,我们最终使用MD5作为模型文件格式:
1. 它支持骨骼动画。
2. 它是文本格式文件,便于查错。
3. 它是一种通用的文件格式而非我们自定义的文件格式,因此可以使用多种模型查看器浏览。
4. 它的压缩率在文本格式文件中比较高。

当然了,解析文本格式的模型有个非常严重的问题,那就是解析速度慢得难以忍受。因为解析模型需要不断地在AS3中调用string.getCharAt(),而这是个非常耗时的操作。

使用AMF加速模型解析

我首先做的一个尝试就是使用Adobe自带的AMF格式加速模型解析。具体做法就是先把解析好的模型序列化为AMF然后保存成文件。当加载的使用ByteArray.readObject()反序列化文件。这个方法解析模型相当快。快到什么程度呢?解析一个3000面的模型仅需要6毫秒。然而,序列化成AMF文件后,模型体积会增大,且无法使用zip进一步压缩。因此只能忍痛放弃。

使用JSON加速模型解析

其实解析模型慢的主要原因是AS3本身慢,假如能把解析工作移至C++中做,一切都会变得很美好。对于这点,我并没有选择使用FlasCC,原因有两个,一是Flash官方已经放弃FlasCC了(囧),二是使用FlasCC需要引入一个1m大小的库(坑爹)。

所以我就想到了使用JSON。Flash本身是自带JSON解析的,而且效率很高。同时,将MD5转成JSON格式非常简单,还保留了可读性。同样的一个3000面模型,JSON解析部分耗时9毫秒。最终,我们决定使用JSON格式。

进一步压缩文件大小

使用3ds Max导出的模型顶点数据精度都很高,有些甚至到了小数点后8位。实际上由于游戏中我们并不需要显示那么大的模型,所以要求的精度也没有那么高。根据实测,模型文件精确到小数点后4位,动作文件精确到小数点后6位,从视觉上看不出和原文件有什么不同。经过这一步处理,文件的体积可以进一步缩小20%-25%。

分片加载

实际上模型除了json本身的解析外,还需要根据骨骼和权重生成模型,计算法线等。一般来说,一个模型的解析耗时在30-50毫秒之间(AMF则不同。由于AMF是把内存中的模型直接序列化成文件,因此在反序列化时不需要做任何额外处理)。对于一个目标帧率为60的游戏来说,这个时间远远超出了一帧16毫秒。因此,最后要做的事情就是把任务分拆成小块,每帧只进行一部分的加载。经过这样的处理以后,就可以实现在场景中动态加载模型时不卡帧。

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注