Unity 场景分页插件 World Streamer 支持无限大地图的解决方案(一)

简介:

翻译官方文档加上自己的一些理解。

 

参考: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是一个回调,可以把额外的读取结束处理函数放到这里来。其他不讲了,很简单。
 
 
(4.5)Floating Point Fix system 浮点修正系统。
如果你的场景太大(这里我特意邮件问了一下老外,大约10K*10K的,也就是100平方公里的世界,都不需要这个功能,所以一般情况下是用不到的,除非你要搞个魔兽世界那么大的世界,一般也就MMO能用上吧……),或者循环,你需要浮点修正系统。如果你的场景过大,物理和其他依赖于对象位置的系统,将会在计算的时候失去精度。
 
 
WorldMover将会不断的重置你的世界位置。但是这么做会很耗,所以不要太频繁。
此外这个系统不支持静态批次和NavMesh。
使用Prefab:"_World_Mover"来获得浮点修正功能。
XYZ Tile Range:如果设置(2,2,2)意味着每经过两个虚拟格子,重置一次。控制粒度的参数。
然后,你大爷的,有需要填一遍Streamers
CurrentMove:Local Player Position - Current Move = PlayerRealPosition.常用于RPC中的位置修正。
注意如果物件需要跟随Player,那么需要为其添加ObejctToMove脚本。
(我的独立游戏应该还没大到需要这么做)
 
(4.6)Looping,略掉,我用不上。
 
(4.7)Ring streaming idea
这玩意可以用来完成一些LOD的功能
原理,内圈读 高清模组范围,外圈读低模模组,把内圈扣掉,相当于近处用清晰模组,远处用低模。UnityTerrain本身不支持LOD,可以用这种方式实现类似LOD的效果。
 
(4.8)Physics Manager物理管理器
超过距离玩家指定距离,物理将会被Freeze。
使用Prefab“_PhysicCulling_Test”
 
(4.9)Terrain Cull System 地形裁剪系统
Terrain Culling System这个脚本应该被附加到每个地形块上,当地形距离玩家过远时,将被裁剪。
 
(4.10) Player in safe place during data loading 玩家安全位置
如果你希望把Player移动到安全地点,直到读取或传送结束,你需要使用“Safe_Place_Spawn_and_Teleport”Prefab.这个系统也支持已经生成完的Player。
Streamers:填写影响SafePlace系统的Streamers。
SafePosition:Player将被移动到这个安全地点,直到读取完成。
Player:如果之前的选项勾选了“Spwaned Player ”(Player没有放到场景里,而是Spwan出来的,并且带有Player标签的。),这里需要留空。一旦Player被Spwan出来,他会在SafePlace等待游戏开始。
 
(4.11) GI and Lighting manager(unity 5.5+)
菜单:WorldStreamer->LightingManger。 提供一个允许你批量设置多个场景的光照的途径。直接把SceneCollection拖进去,即可。
本文转自jiahuafu博客园博客,原文链接http://www.cnblogs.com/jiahuafu/p/8287223.html如需转载请自行联系原作者

jiahuafu

相关文章
|
2月前
|
图形学
Unity 不同Scene场景转换(简)
本文提供了Unity中实现场景转换的基本方法,包括编写传送脚本、创建传送门和玩家对象,并通过触发器实现玩家触碰传送门时切换到另一个场景的功能。
Unity 不同Scene场景转换(简)
|
2月前
|
图形学
小功能⭐️Unity获取场景中所有物体
小功能⭐️Unity获取场景中所有物体
小功能⭐️Unity获取场景中所有物体
|
2月前
|
传感器 开发工具 vr&ar
ManoMotion⭐二、Unity手势识别插件简介,及效果录屏
ManoMotion⭐二、Unity手势识别插件简介,及效果录屏
|
2月前
|
Linux 开发工具 图形学
Unity下实现跨平台的RTMP推流|轻量级RTSP服务|RTMP播放|RTSP播放低延迟解决方案
自2018年起,我们成功实现了Unity环境下的低延迟RTSP|RTMP播放,达到毫秒级延迟,获得业界广泛认可。现已覆盖Windows、Android、iOS与Linux平台的RTMP推送、轻量级RTSP服务及RTSP|RTMP播放。通过高效采集Unity窗口或摄像头数据,并利用原生SDK进行编码与推送,确保了数据传输的高速性。此外,播放器支持多路视频同时播放,适应不同分辨率,并保持长时间运行稳定。更多技术细节和技术博文,请参考相关链接。
177 1
|
1月前
|
图形学 C++ C#
Unity插件开发全攻略:从零起步教你用C++扩展游戏功能,解锁Unity新玩法的详细步骤与实战技巧大公开
【8月更文挑战第31天】Unity 是一款功能强大的游戏开发引擎,支持多平台发布并拥有丰富的插件生态系统。本文介绍 Unity 插件开发基础,帮助读者从零开始编写自定义插件以扩展其功能。插件通常用 C++ 编写,通过 Mono C# 运行时调用,需在不同平台上编译。文中详细讲解了开发环境搭建、简单插件编写及在 Unity 中调用的方法,包括创建 C# 封装脚本和处理跨平台问题,助力开发者提升游戏开发效率。
107 0
|
2月前
|
开发者 图形学 iOS开发
掌握Unity的跨平台部署与发布秘籍,让你的游戏作品在多个平台上大放异彩——从基础设置到高级优化,深入解析一站式游戏开发解决方案的每一个细节,带你领略高效发布流程的魅力所在
【8月更文挑战第31天】跨平台游戏开发是当今游戏产业的热点,尤其在移动设备普及的背景下更为重要。作为领先的游戏开发引擎,Unity以其卓越的跨平台支持能力脱颖而出,能够将游戏轻松部署至iOS、Android、PC、Mac、Web及游戏主机等多个平台。本文通过杂文形式探讨Unity在各平台的部署与发布策略,并提供具体实例,涵盖项目设置、性能优化、打包流程及发布前准备等关键环节,助力开发者充分利用Unity的强大功能,实现多平台游戏开发。
80 0
|
4月前
|
数据可视化 大数据 API
【推荐100个unity插件之22】基于UGUI的功能强大的简单易用的Unity数据可视化图表插件——XCharts3.0插件的使用
【推荐100个unity插件之22】基于UGUI的功能强大的简单易用的Unity数据可视化图表插件——XCharts3.0插件的使用
143 0
|
4月前
|
自然语言处理 搜索推荐 API
【推荐100个unity插件之21】unity实现多语言切换功能——Localization插件的使用
【推荐100个unity插件之21】unity实现多语言切换功能——Localization插件的使用
146 0
|
4月前
|
JSON 开发框架 API
【推荐100个unity插件之20】一个强大的JSON处理库——Newtonsoft.Json(也称为Json.NET)
【推荐100个unity插件之20】一个强大的JSON处理库——Newtonsoft.Json(也称为Json.NET)
309 0
|
2月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
135 6