引擎工具链高级概念与应用
引擎工具链高级概念与应用
游戏制作一览

世界编辑器 World Editor
A hub for everything to buid the world


编辑器的视口是为游戏世界构建的窗口
引擎会提供有一些Editor-only代码专门为编辑发布的,不应该在游戏打包的时候使用
Viewport是需要支持多个view窗口

在编辑窗口中所有的Object都应该是选中编辑的
比如虚幻的Actor

根据用户需求,提供不同的view窗口来管理对象


提供浏览窗口管理不同资源池

鼠标拾取的两种方式
- Ray Casting(比较耗性能,没有缓存)
- RTT: 把object的ID透射到屏幕像素上提高鼠标选择的精确度
对于透明物体和粒子特效的选取,通过给物体绑定一个可以选取操作的对象。
地形编辑器 Terrain Editor


高度笔刷需要提供平滑变化,自定义功能

实例笔刷提供了批量生成的功能

环境变换设置很多是插件提供的,需要预留插件空间


需要定义环境编辑的变化规则
描述一些比如树的生长规则、河流的构建规则,然后用程序化生成
挑战:程序化生成后,如何进行局部修改不影响全局生成的数据
编辑器插件架构 Editor Plugin Architecture

横向的各类别系统和纵向的不同类别物体构成了一个交叉矩阵
给world Actor设计一个Plugin的时候,纵向和横向都需要
插件协同组合的四种模式:


覆盖 Covered 替换掉原有的逻辑
分布式 Disributed 每个插件都会执行,最后合并
流水线 Pipeline 进行数据不断处理和导出
洋葱圈 Onion rings 对别的插件进行输入输出操作,比如地编

需要版本控制来控制插件的兼容性,比如虚幻引擎升级到5.1后,插件是需要更新才能正常工作
设计叙事工具 Design Narrative Tools
游戏变现越来越像电影,基于一个时间轴去变化

线性叙事

Sequencer把每个物体在世界中的变化通过Track来追踪
Actor的每个属性都可以定义在时间轴的变化
当这些变化集中到一个Timeline上,可设定key frame来标记关键节点进行插值
最终通过这个展现一个丰富的变化,比如地平线的cutscene就是这样做的

一个简单的sequencer的关键帧插值示例
反射和游戏逻辑 Reflections and Gameplay

Reflection 是实现引擎代码和工具之间的重要桥梁,把代码实现的功能接口开放给不同的游戏生产者(例如蓝图就是通过Reflection实现)。
提供可视化编程的可扩展性

反射意味着当写完一段代码后系统会告诉你到底有那些新的功能被暴露出来,
这样其他调用者不需要编译链接这段代码就能调用这些功能接口。

反射为代码和工具构建了很好的桥梁
引擎实现的功能通过反射生成一个表,告诉使用者这个引擎开放了那些类的接口,有那些功能和数据可以访问
也生成一堆invoke的调用函数,通过set/get可以修改和获取数据。这样在工具端就非常简单地访问这些类的属性和方法。
可视化脚本降低了设计师和艺术家使用的门槛,提供了更自然的表达方式
如何在C++中实现反射


现代高级语言都需要通过类似于GPL规范的编译系统编译出来
整个编译系统由非常规范的Pipeline, 比如语法分析Parse, 生成ASD抽象语法树,形成中间代码,最后生成最终的target code.

Clang编译器把语言翻译成ASD抽象语法树
如上图C++的类经过Clang分析后形成一个非常好解读的树状结构的表
通过这个表我们很容易地把任何一个类的函数,成员提取出来然后生成我们想要的schema


Picclo就是通过开源的Clang编译器从抽象语法树生成Schema
并在内存中构建一个临时的Schema进行访问

Fields标记这个类都被反射出来
WhiteListFields标记只有Enable关键字的时候才会反射出来

通过宏来实现反射控制
C++编译器在编译exe的时候所有描述都是无效的,
但是通过__attribute__关键字加上annotate可加入各种标记,这样在生成的ASD代码里面可以看到设置的标记
实际上就是非常简单的字符游戏
Unreal反射的基础方法和结构和上面的描述非常接近

从上面反射简单描述来看给一段C++代码通过加上特殊标记就能找到所有想要的结构,还能生成它的schema描述。
Reflection还需要提供get,set,invoke三类函数来获取,修改和调用,涉及到代码渲染的概念:


代码渲染自动生成代码,避免冗余的代码编写
自动生成也避免手动的错误,非常完美地分离数据和逻辑

Mustanche(胡子) 加入很多大括号来描述代码,通过数据语法翻译自动渲染出想要的代码, 下面是简单的过程:

协同编辑 Collaborative Editing
如何实现:一、主要是解决多人操作时的冲突问题;二、把每一个操作步骤进行原子化处理


合并冲突
- 资产分割 Split Assets
- 分层(地形层、植被层、房屋层)
- 分层很难分好,且有相互依赖
- 分割世界(地图分块)
- 可能出现跨界问题
- 分层(地形层、植被层、房屋层)
- 一个对象一个文件(预制)
- 小文件多,操作系统不友好


协同编辑–对所有的操作进行原子化操作

协同操作时候的Undo/Redo很难处理,可以通过加锁处理


但是锁不是万能的,比如下图:

其他解决问题的方案


现在的协同编辑让所有的操作在server结算完再统一发送给client, 还是存在下面的问题

服务器可能会奔溃,所以必须保持服务器的健壮性
相关资料


