动态加载资源
如今很多游戏engine宣称自己支持动态加载地图,也就是说可以作到跨地图时的零读取时间。听起来很高深的技术,实际不难实现,当然我们在大话西游和梦幻西游中早已经实现了。最近我正在考虑更加通用的解决方案。
先说说基本的思路。也就是我们需要把地图数据切割成小块,让每一块的数据读取解析量并不太大。然后,就可以根据玩家所在坐标读取最小数据量的数据。当玩家移动的时候,利用一些机器闲置时间去读周围的场景,或者进一步可以根据玩家移动方向把前方数据预读的优先级别调高。
其实,这个方案可以被推广到所有的游戏资源。其实,我们可以给每个资源文件都放置一个通用的数据域存放一些建议关联文件列表。如果是地图块的话,它的建议依赖文件就是它周围的地图块,或者是人为设置过跳转点的目标块。
而模型文件则可以把它依赖的贴图,骨骼文件做为建议依赖资源。地图场景文件可以建议依赖一些摆放在上面的模型文件。
有了这些依赖关系,我们在读取某个指定资源文件后,可以用一个独立线程预先加载一些可能下一步要加载数据,也可以由逻辑层主动通知一些预测信息。例如我向东向移动,可以通知 I/O 线程,东边的相关资源优先级别高一些,I/O 线程则去调整预读队列的次序。
I/O 线程的设计是比较复杂的,我的最初想法是建立一个大的 cache, 以内存页对齐(IA32 下是 4K)。如果数据被预读了,主线程索要数据的时候,用共享内存的方式,将 cache 中的数据块交换出去。
经过和同事的讨论,一个做 OS 的同事提示我,设计可以更简洁一些。因为现在 OS 对 file I/O 的 cache 机制都非常完善了,预读只需要去真的读一下文件即可,不需要再去自己做 cache,自己做 cache 只能节省一些数据 copy 的操作,但是其逻辑的复杂程度还有页表操作的负担不一定划算,所以我们只用专心做好预读逻辑即可。
这样的动态加载的资源管理模块,完全可以做的对主线程完全透明。我们的主线程只需要按阻塞模式去读取文件就够了。
但是,如果读取文件还伴随着耗时的解码过程。比如解 jpeg,解压缩,解密。那么我们最好自己做 cache 了。
Comments
Posted by: Beatless | (10) September 2, 2012 12:32 PM
Posted by: Mandi Zu | (9) March 24, 2007 10:58 PM
Posted by: Mandi Zu | (8) March 24, 2007 10:56 PM
Posted by: Anonymous | (7) August 29, 2006 02:28 PM
Posted by: gameboy | (6) January 16, 2006 06:22 PM
Posted by: flyingxu | (5) January 13, 2006 02:06 PM
Posted by: Cloud | (4) January 10, 2006 02:24 PM
Posted by: ZERO | (3) January 10, 2006 02:18 AM
Posted by: Cloud | (2) January 6, 2006 05:22 PM
Posted by: ZERO | (1) January 6, 2006 03:12 PM