Unity在元宇宙到来之际如何提高效率?Unity技术开放日北京站工业专场中,Unity中国解决方案工程师舒润萱分享了主题演讲《Unity云原生分布式运行时》。
舒润萱:各位嘉宾大家下午好,我叫舒润萱,现在在Unity中国担任解决方案工程师,今天我从以下几个方面和大家分享一下云原生分布式运行时。
首先我想带大家一起看一下我们对元宇宙到底是怎么定义的,这里引用Unity CEO,JR的观点,我们认为元宇宙是下一代的英特网,将一直是实时的,大部分是3D的,将是有交互的,并且是社交性的,而且需要是持久的。
稍微概括一下元宇宙的特征,元宇宙必然是一个规模庞大的世界,它的参与人数非常多,环境规模非常大,交互种类非常复杂。同时,还是一个3D实时交互,场景将是沉浸式3D,玩家间实时互动,是一个高响应度高互动性的场景。最后是持续稳定的世界,虚拟世界玩家在整个参与过程中世界的改变会随时间积累保留的。
在这个场景下传统的游戏引擎将会面临很多挑战。首先将会面临巨大的渲染压力,就像刚才说的,元宇宙必将是一个大规模的高清世界,里面拥有数量庞大的动态或静态元素。同时,传统实时交互引擎还会面临巨大计算压力,大量玩家进行实时交互,可能会有超大规模的物理仿真需求。传统的引擎也会面临巨大的网络带宽压力,以及在元宇宙场景下需要很大程度的可扩展性和可伸缩性,这些都是传统的引擎在现在元宇宙场景下会面临的挑战。
因此就提出了一个Unity云原生分布式运行时框架,由两部分组成,一个是Unity云原生分布式渲染,第二是Unity云原生分布式计算,这个框架基于DOTS。大家知道使用Unity DOTS开发的应用自然而然有一个存算分离的属性,数据和用来处理数据的代码是解耦的,这样一个架构是非常并行的,在DOTS下的代码性能比传统的高很多。

Unity云原生分布式渲染

首先介绍一下Unity分布式渲染。
这是一个传统网络的Client、Server架构,如果我们开发一个联网体验,这是一个简单的切入点。这个架构下有一个中心化的Server,它将进行大部分游戏计算和维系这个游戏世界,用户端处理用户的输入,把虚拟世界展现在用户面前。
分布式渲染第一件事情就是把用户Client端拆分成这个架构,多引入了两个角色,称为Merger和Renderer(运行在云上)。Merger负责合并Renderer的画面,以及接收转发用户的输入。Renderer负责的很简单,就是渲染游戏世界的角色。Server除了之前负责的处理逻辑计算、管理游戏世界的任务以外,还需要向Render Group同步世界数据,管理Render Group更新频率。
分布式就是把一个完整的渲染任务拆分成不同的任务,有几种不同的拆分方式,首先是通过屏幕空间划分,比如这里我们把一个完整画面渲染拆分成四部分。
当然也可以进行时间上的拆分,比如让这台机器渲染第一帧,下一台机器渲染第二帧,这也是一种拆分方式。
还可以根据场景拆分,可以在Merger上渲染一个近景,远景通过不同的Renderer同时渲染同时推流给Merger。
这个拆分方式是非常自由的。为什么可以做到如此自由的拆分方式呢,主要是分布式渲染框架提供了三个很重要的能力。第一个能力就是统一的渲染调度,在做分布式渲染的时候,像渲染或实时交互的应用它的运行是有频率的,在这里Renderer又会对一个场景不同部分进行渲染,它们更新的频率很有可能是差距不大,但是有差距的,这时候需要一个系统进行统一调度,才能保证在合并的时候完美地找到每一帧的画面。
第二,涉及到渲染的Merger和Renderer的机器必须要有一致的世界数据,像动态物体,像角色在场景里走来走去,如果在这些机器上角色的位置是不一致的,出来的画面是拼不起来的,分布式渲染也提供一个让Merger和Renderer在同一时刻拥有完全一致的世界数据的能力。
第三个能力就是高效的画面传输,因为在这个框架里合并的时候,画面是从Renderer直接过来,也就是说这些画面将通过网络从Renderer传输给Merger再由Merger进行最终合并。所以这个传输的效率,包括它的延迟和带宽都是非常关键的,分布式渲染框架就是提供了这样三个能力,只要有这三个能力,如何拆分、如何合并渲染任务是完全自由的,可以由业务层根据自己的业务需求去自定义。

Unity云原生分布式计算

下面介绍一下分布式计算。回到刚才分布式渲染的框架图来看,这个框架图非常有迷惑性,因为只画了两个Client。如刚才所说,元宇宙场景必然是一个超大规模的交互,会有很多用户一起参与进来,这就会面临一个中心化的Server同时服务于成千上万个Client机器,肯定是不现实的。在此我们提出了分布式计算的概念,相当于在Server这边也可以把Server的计算任务拆散,引入了一个新的角色,叫Remote。
在这个架构下,Server除了之前管理自己的游戏世界数据以外,还要去跟Remote交互。Remote主要负责计算,Server就需要从自己的世界数据里拿出一些需要更新的数据,通过网络发送给Remote,还需要从Remote那边获取更新之后的结果,再更新自己世界数据,Remote就会从Server那边拿到数据以后进行计算。
这个事情为什么是可行的,这边是一个简单的ECS架构图,可以把Server上的东西分成两种,一种是Component,这就是世界数据,还有在Server上运行的逻辑Code,是逻辑运算。整个ECS运行逻辑,简单说就是我们有数据,有一个正在运行的System逻辑代码,逻辑代码作用就是拿到它关注的数据,把它更新成新的数据。
这就是ECS为什么有存算分离的特性,可以看到System本身是不需要一定运行在Server本地的东西,它只关注输入数据是什么,输出数据是什么,我们就可以把System这个东西放到另一个进程上做,也可以放到另一台机器上做。Server上会保留世界数据,因为这里有一个世界数据进行管理,进行运算的时候,Server通过网络把Remote和System感兴趣的数据通过网络发送到Remote,Remote获得这个数据以后可以在本地进行像刚才那样的ECS运算。
之后输出的新的数据会通过网络发回给Server,Server就可以根据这个新数据更新它的世界数据,这样一个计算任务可以分配给不同的机器做。
这是分配计算任务的代码,我们提供API是一个ECS系统,它有一个它感兴趣的数据,开发者可以定义感兴趣的是什么样的Entity,这边定义了一个Query,运行的时候想发送走的数据就会被这个系统以我们定义的类型发送走。
如果我们想要把代码,比如之前写好的ECS代码改成运行在Remote的代码,只要在写好的System的代码加上一个叫UpdateInWorld(WorldType.Remote)的Attribute,这个系统就会只在Remote运行,配合之前自己定义好的感兴趣的是什么样的Entity以及上面有什么Component,以及把刚才定义好的脚本跑起来就可以了。只要做好这几个事情,自己定义的Component就会自动发送到Remote上,Remote就会自动运行这上面的System,更新好的数据也会自动发回Server。

DEMO

下面给大家展示几个DEMO。
第一是方块坍塌,它是大规模物理+网络传输的DEMO,物理是由DOTS Physics提供。这两个视频上面开启了分布式计算,下面没有开启分布式计算。这个场景里总共有89600个方块,分布式计算用了4个Remote,得到结果是上面的视频Server端更新帧率是10FPS,仿真是非常慢的,下面这个视频在Remote帧率是37FPS左右,仿真速度成倍于上面的仿真速度,这就是用了四个Remote节点获得了接近四倍的提升。我这里写了一下测试环境,大家可以看一下。
下面是Unity中国和中国移动咪咕合作的直播互动剧项目,名字叫青霄。这个项目刚刚发布,估计很快会上线。这个项目主要亮点是使用超高清材质,无论是贴图还是模型都是非常高清的,它是在这个场景下实现实时互动的项目。
这个项目使用了分布式渲染和分布式计算,我们只展示分布式渲染的提升,这个场景大有3亿个三角面,截图上写的是2.6亿,为了渲染这个庞大场景使用了GPU Driven技术,允许我们做到更细致的Visibility Culling和Frustum Culling。
这是1080P的对比,上面是单机,下面是分布式计算。在1080P场景下分布式渲染获得提升并不是很多,因为在这个场景下在某些镜头下已经不是GPU-Bound场景。但是,即便没有多少提升,也不会因为分布式框架带来额外管理成本导致帧率降低。
这边是4K下的对比,同样是开了三个分布式渲染节点,这三个节点分别渲染画面的左中右三个部分,是一个纵向的拆分。在4K场景下获得一个比较好的FPS提升的效果,DEMO测下来有1.5到2.8倍的提升,因为镜头不同,FPS也不太一样,所以没有绝对数值可以说出来,波动范围是1.5倍到2.8倍。
最后一个DEMO是Unity中国与中国移动咪咕合作的星际广场的项目,这是在世界杯期间为了服务于万人同屏大规模用户的实时交互做的这么一个项目。这个项目物理是由Motphys提供的分布式物理,也是用了分布式渲染和分布式计算的技术。
这是近景的视角,场景有五千人,渲染分辨率是4K,这两个画面都是开了分布式计算,下面这个开了分布式渲染,也是三个Renderers的配置,这个场景下从单机25FPS提升到48FPS,有接近两倍的提升。
这是一个空场景全景环绕镜头,也是4K渲染分辨率,同时也是开了三个Renderers,这个场景可以做到从30FPS到70FPS提升。
这个场景跟刚才的场景一样,也是全景环绕的视角,上面也是五千人,跟第一个场景一样,在4K环境下用三个Renderers结构把这个程序从15FPS提升到30FPS,这个提升非常关键,因为我们在实时渲染领域会认为15FPS是我们无法接受的帧率,30FPS勉强能玩。
下面介绍一下产品规划,我们希望在今年年底之前对外发布一个试验版的框架,但在此之前还有很多事情需要做。首先是端云协同,如果大家记得之前的架构图,可以发现在用户端上只运行一个类似于视频播放器的东西,端上算力是被浪费掉的,用户端也是有可观算力的,也就是说我们希望能利用整个运行环境里所有的算力,希望在用户端上也可以运行Unity Player,可以在端上进行Unity内部运算。因为用户端上的算力毕竟有限,我们的质量肯定会下降,所以我们希望能够跨Quality Settings做一些事情,端上运行的Unity Player可能是一个低质量的,但云端依然可以使用高Quality Settings。
开发者体验方面,由于目前分布式框架没法在Editor上运行,导致开发者想要看到真实的分布式运行时效果需要先构建出包,大大增加了开发者的迭代时间和试错成本。我们希望通过分布式Game View在Editor里运行分布式,并配合CI/自动性能报告,云端构建出包。
还有希望运行时是可编程的形式。不同业务需求面临不同的场景,在这种不同场景下框架需要一定自由度适应不同的性能瓶颈,我们希望运行时可以提供一些预设好的分配任务的方式,同时可以提供让开发者自定义的方式,这就是Scriptable分布式。
多Server/层级式Server可以用来解决大量用户导致的高连接数和带宽瓶颈问题,以及高可用场景。
Remote节点希望能完成动态扩容和负载均衡。随着元宇宙项目运行,很可能会遇到高峰期和低谷期,有时候Remote需要更多,有时候不需要那么多,这时就需要动态扩容和负载均衡的功能。
除此之外还希望支持GameObject/MonoBehaviour,还有RayTracing支持,以及包括边缘计算,还有云原生组件,RDMA网络传输等。还有MPI、可微渲染器这样的技术,可以用一个渲染机器服务于多个不同的视角,也就是多个不同的用户。这些都是我们未来可能想尝试的一些方向。
我今天分享就到这里,谢谢大家。
Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐