游戏场景分段动态加载

Jul 10, 2016


Unity游戏中,有着各种“动态”优化手段。以往大家对于场景的优化采用loading异步加载,一次性将场景的全部内容都加载出来。虽说在摄像机之外的内容会自动剔除,但场景内的元素依旧存在内存中,且loading时间过程对玩家的体验也就一般,前几天想到对场景的另外一种优化手段:场景分段加载。

所谓分段,就算是将场景分成若干段,这些段视玩家在场景内的位置动态加载出来。如果玩家在这个场景里所做的操作不涉及到其他的段,那么这些段可能在玩家玩的过程中永远都不会加载。以常见的过关式场景为例,玩家在过程中是不断推进的,假设这个场景分为A->B->C->D段,首先默认加载的是A段,那么玩家在A段内时,BCD段都不会被加载,当玩家进入D段并且过关成功后会直接进入结算界面或者被传送到另外一个场景里,也就是说进入D段的时候ABC段可以直接destory了,在这个过程里,很有可能只有一个或者两个场景在内存里并被渲染,大大的提高了渲染效率,到达节约运行时内存的目的。

至于实现方式倒也简单,因为工作原因不能将源代码和场景放出来。实现方式也需要美术配合。

在美术拼接场景的时候,将场景分为多个段,将场景的第一段定位.unity,其他的段则为prefab,在.unity和prefab中放置空的GameObject,添加Collider组件用户当与玩家发生碰撞的时候,说明此时需要加载下一个场景段,假设一个场景分为ABCD段,那么美术在拼接场景的时候,大致如下:

A–(Load Collider)—(Unload Collider)->B–(Load Collider)—(Unload Collider)->C–(Load Collider)—(Unload Collider)->D–(Load Collider)—(Unload Collider)

当玩家与LoadCollider发生碰撞的时候,将B段动态加载出来作为场景的一部分,进入B段之后,如果按照游戏的设定玩家进入B段之后不能再回到A段的话,当玩家在B段内与UnloadCollider发生碰撞时,那么A段可以直接destory或者unvisible。

那么程序要做的是,就是在场景(此时只有A段)加载出来之后,统计当前场景的LoadCollider和UnloadCollier个数,获取LoadCollider和UnloadCollider对象身上的段prefab路径,获得prefab的handler(资源handler提早获得,否则在发生碰撞的时候再去找handler也会有一定开销),在发生碰撞的时候即时去加载和卸载。

当前只说了发生碰撞的时候才进行加载和卸载,实际上还有一种情况也会进行加载和卸载,那就是摄像机变化,当摄像机的内容涉及到其他的段的时候,需要在摄像机的可视范围(这部分需要额外计算摄像机的可视范围在场景内的变化)内涉及其他段时进行加载(当然也可以即时加载,视接受程度而定)。