Unity场景分页插件WorldStreamer⽀持⽆限⼤地图的解决⽅案
(⼀)
翻译官⽅⽂档加上⾃⼰的⼀些理解。
参考:WorldStreamer官⽅⽂档。
⽬标:将我⾃⼰的WorldManager与WorldStreamer结合,让WorldStreamer⽀持开放世界建筑系统。
⼀、原理
创建虚拟grid,将⼤世界分成⼩块管理。设置⼀个“参照点”(通常是Player,如果是RTS,则是Camera),当参照点⾜够接近某个虚拟格⼦,或碰到碰撞体时,将其异步加载进来。
块加载是可以分层处理的,分层的⽬的是为不同的物件提供不同的Grid粒度。⽐如地形,房屋,和房屋⾥的家具,等是需要不同的粒度的,放屋⾥的家具只有玩家⾥的⾜够近才有必要加载,⽽地形则需要在玩家能看到的时候,就加载,甚⾄如光照,声⾳,特效这些虚头巴脑的东西,也可以分层。这个系统也可以作为LOD来使⽤,当玩家离得⾜够远时,可以⽤简单的Mesh替代地形。这样做⾮常省CPU和内存,因为Unity的地形⾮常耗。分层使得分⼯合作成为可能,当然做独⽴游戏的时候就⽼⼦⼀个⼈,这个就懒得写了。
WorldStreamer⽜逼的地⽅是在Build版本中,在Editor中使⽤WorldStreamer会导致⼀些烘焙,批处理操作转移到运⾏时,简单说就是很耗,可以临时关掉Unity的静态批次(static batching)解决这个问题,在Editor中DrawCall会增加,但是发布版本不会有问题。
⼆:准备
Work场景:拆分前的⼤世界
物件分类:分类。
GamePlay场景:存放各种不需要流处理的物件:Player,Camera,DirectionalLight,各种⾃定义的Managers。
注意点击Streamer.cs ⾯板上的Add Scenes To Build Scenes 否则,这些Grid场景是不会被加载的。
三、组件
·SceneSplitter:从你的场景对象创建虚拟Grid和层。他也可以从虚拟Grid元素产⽣场景。在场景⽣成过程中,SceneSplitter也会产出SceneCollection
并以“SC_Prefix”.scenc命名。每个层都会有⼀个SceneColliction
·SceneCollections:保存场景信息,如Grid元素⼤⼩,世界⼤⼩等细节。不需要⼿动填写,这些数据在⽣成场景时,由sceneSplitter或者LocalAreaUpdater填写。
·SceneObjects:与ScencCollenction连接,他们在⽣成场景时,由sceneSplitter或者LocalAreaUpdater⽣成或者刷新。
·StreamerPrefabns(Major,Minor):持有并使⽤“SC+Prefix”在你的GameplayScene中。你的第⼀个Streamer应该是Major。他负责:场景,⼤物件(如果你不使⽤Terrains,所有的物件如果你只有⼀个层)所有其他的Streamer必须是Minor。
·ColliderStreamers:他们持有当某些collider被碰触后需要读取的场景。
·Collider_Stream_Manager:这是⼀个Prefab。赋予你流式读取场景物件通过ColliderStreamers。他也使你能够通过隐藏在Grid元素中的碰撞体,载⼊场景。他也可以让你产⽣“俄罗斯套娃”那样的场景管理,流式场景⾥⾯读取流式场景。(估计我⽤不到)
·LocalAreaUpdater:场景融合,读取局部场景,刷新,修改,移除已经分离的世界。允许多⼈同时编辑同⼀区域。
·StreamerGUI:场景读取,传送,重⽣,时候⽤到的读取页⾯。
·WorldMover。使⽤了“浮点数修复系统”重定位世界坐标。同时保存真实坐标与局部坐标的关联。这对已经spawn的对象和服务器通讯是很有⽤的。
·PlayerMover。这个脚本⽤于移动Player到安全地带,直到初始化数据和读取/传送完成。
·PlayerTeleport。这个对象负责管理传送点,重⽣点,可以为动态物件
·ObjectgToMove:这个脚本在浮点修复系统重置位置时,持有⾮流式物件和⾓⾊之间的关联。
·TerrainNeighbour:负责混合Terrain的边缘,Terrain必须有同步的LOD,否则,Terrain边缘将会有⼩洞。这玩意必须被放到游戏场景中。
·TerrainCullingSystem:性能优化。
PhysicCullingSystem:物理优化。
ObjectParent:当拆分过程中需要分类时,这个脚本需要被附加到Hierarchy⽗节点上。
四、应⽤
(4.1)SceneSplitter
强烈建议在拆分的时候建议将相关内容拷贝到⼀个新的场景“Work”Scene,⽽那些常规内容,⽐如DirectionalLight,Player等放在GamePlayScene中。
·⾄少需要⼀个Layer。
·太空游戏,需要XYZ轴,RTS,RPG⼀般只需要XZ轴,但是如果玩家飞的很⾼的时候,需要把地⾯隐藏,也可以使⽤Y。
·Size不应该过⼤,这样性能损失很⾼,也不能过⼩,这样的话,⼤型建筑就没法划分了。
·对于Unity的Terrain,XZsize必须和地形的Length与Width⼀致。
·分层是根据前缀进⾏的,如果没有前缀,所有的物件会被扔到你⼀个层⾥⾯(官⽅说这么做是为了留出Tag和Layer给开发者,⽤作其他⽤途,所以没有⽤tag和Layer分层)
·最好去掉⽗⼦层次关系,但是不这么做也没什么⼤问题。官⽅推荐这么做是因为,如果B是A的⼦物件,A在(1,1)区块,但是B的轴⼼位置在(1,2)区块,那么B本应该分配到(1,2)却因为⽗⼦关系,被分到了(1,1),这样加载的时候,看起来会有些奇怪。但是如果B和A的轴⼼都在(1,1)区块,就没有区别了。
·
LayerOrder是有意义的,如果你把⼀个GameObjectgPrefix为空的Layer放在第⼀位,他会把所有的GameObjec收纳,但是如果你把他放在最后的位置,他就会起到“兜底⼉”的作⽤。
BuildSettings标签页(图:略过),这⾥可以看到SceneCollections是⼀个被Split的Scene的管理集合,⼀个SceneCollection对应⼀个层。每个SceneCollection会被做成⼀个Prefab。
4.2 Streamer Objects/Prefabs和他们的设置
官⽅⼿册截图
SceneCollection:把4.1⽣成的Prefab拖过来。
LoadingRange:预读取范围,1=9宫格。2=25格。
Deloading range:卸载场景距离,⾸先检查距离,然后检查延迟时间,场景不是马上卸载的,因为玩家很有可能“刚迈出去⼀步,⼜被揍回来了。”如果你的场景是循环的,那么卸载距离应该⼩于场景总距离的⼀半-1。deloading size <world size / 2 -1
Position check:距离检测时间,不是每帧都检测的,那样太蛋疼了。
Destroy tile delay:玩家超过Deloading范围后,删除Tile的延迟时间。放置边界处频繁的删除,加载场景。
Max Parallel Scene Loading:同时加载的场景数量,值越低,越顺畅。但是远处场景可能会看起来⼀个⼀个蹦出来的。
Scene Load Wait Frames:场景读取等待时间,如果场景流⽔线读取太慢,很有可能是你把这个值设的太⾼了。
Terrain Neighbours:放置到有TerrainNeighbours.cs脚本的Prefab,⽤于同步TerrainLOD
Looping:地图是否循环读取,⽤于创建⽆限世界。
Spawned Player:Stream需要等待Player创建完成后再开始读取。如果这个选项被勾选,所有Player窗⼝应该留空
(4.3)传送与复⽣
把_PlayerTeleport拖进场景。他的XYZ值将作为传送⽬的地的xyz坐标。
(应该只⽤⼀个PlayerTeleport,然后依据⽬的地,动态调整他的位置,不然岂不是要搞⼀⼤堆_PlayerTeleport物件?反正你⼀次也只能传送到⼀个位置。例如你在A城,有BC两座⽬的地城堡,你在菜单中选中B城,先把PlayerTeleport设置到B城的某地,然后设置PlayerTeleport的位置为改地点,在执⾏传送函数即可。)
推测这玩意就是当你需要传送时,将⽬标地点周围的格⼦预加载,同时将你周围的格⼦全部卸载的东西。参考魔兽世界,即便是开放世界,⾛传送门的时候也
需要读条。
Ui Loading Streamer:读取时UI界⾯,可以直接照着官⽅提供的例⼦改。
Streamer:要把所有的Streamers都拖进去。
WorldMover:如果要使⽤Floating Point Fix 系统,把WorldMover扔进去。
PlayerMover:如果使⽤安全放置系统,把含有对应脚本的物件扔进去。(官⽅提供的是_Safe_Place_Spawn_and_Teleport)
(4.4)读取页⾯设置
分页查询插件
Streamers:这⾥不得不说⼀句,官⽅,真他妈缺⼼眼,这⾥⼜要把Streamers全都设置⼀遍。不能个地⽅集中设置⼀下,其他模块都从这个设置读取吗?
这个没啥解释的,设置这些,估计是为了处理读取的Progress。最后OnDone是⼀个回调,可以把额外的读取结束处理函数放到这⾥来。其他不讲了,很简单。
WaitTime:⽤于计算多少个Virtual Grid受影响的时间,通常设置2-3秒即可。
(4.5)Floating Point Fix system 浮点修正系统。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。