蓝图(blueprint)是一种以C++为编译目标的可视化编程语言,首次出现在虚幻引擎4中,实质上也是为了紧跟low code的时代潮流,用图论取代文本,让开发者不必再拘泥于语法导致的基本问题。图形语言最大的好处在于可以将代码中的各种树形逻辑展示出来,大大提升了开发效率。
本文的重点是用蓝图实现UE4自带的level streaming volume,这玩意翻译过来叫“场景流触发体”,在此之前需要介绍下什么是level streaming(场景流)。
理论基础:和LOD(level of details)始终占用内存的特性不同,场景流可以选择性的流入/流出内存,大大提升效率,尤其是那些躲在室内,从外面看不见的物体,就没必要加载它们了。场景流主要有2个好处:
level(场景)本是content browser中的map类型的uasset文件,但可以在Levels窗口中将它们以层级关系联系起来,本质上是对整个项目进行组件化划分,但最常见的用途就是动态加载场景,比如:
总之,场景动态载入是每一个大型3D游戏的必备。
Tip:在无缝载入情况下,level streaming肉眼是看不到效果的(比如进入房间前),但可以根据World Outliner底部统计数据的变化来判断效果。
所谓的Volume是一个三维的brush(BSP)几何体,看不见摸不着,却能触发碰撞,将之放在Persistent Level中然后绑定到某个sublevel,人物进入volume体内后触发sublevel中所有actor的加载。
做web开发的时候,每次出现一个新api,在所有浏览器兼容它之前,我们总是习惯自己去实现这样一个函数,作为过渡,顺便证明自己理解了它。同理,在LevelStreamingVolume出现之前,通过蓝图或C++来实现这个Volume。
首先创建一个蓝图类,因为要实现可放置,所以蓝图类基于actor创建,同时创建一个等待载入的level:subLevel。
然后给这个actor准备3个组件和1个变量:
其中,cube和box空间上完全重叠,cube用半透明的材质代表“可进入”,text位于它们的上方,效果如下:
希望实现的效果是:当肉体进入这个橙色区域时载入levelId,离开时载出,levelId可以让用户指定,所以要开启“Expose on Spawn”选项。
整个逻辑很简单:先对box监听onComponentBeginOverlap事件,发生重叠时判断参数otherActor是否等于玩家(getPlayerCharacter),如果相等则调用loadStreamLevel(levelId);
载出场景的逻辑与之相反,只要将对应的方法替换成onComponentEndOverlap和unloadStreamLevel即可。
场景流节流
人物进入volume的时候,2个不规则的几何体发生重叠,可能会触发好几次重叠事件,所以有必要做一个节流(throttle)减少开销。
调用loadStreamLevel之前判断一下,如果场景已经加载,则停止向下执行:我们通过getStreamingLevel(levelId)获得场景的引用,再传入isLevelLoaded判断加载状态。所以整个蓝图如下:
这是载入部分,载出部分基本对称,就不放图了。自此,引擎自带的Level Streaming Volume被蓝图成功地模拟了。