十四、工具链:高级概念及应用

14.1 World Editor

A hub for everything to build the world

14.1.1 World Editor中的编辑工具

14.1.1.1 Editor Viewport

用户和游戏世界交互的窗口

  • 底层跑的实际上就是引擎的runtime,但是是以editor mode

  • 引擎有一些代码会是editor-only

  • Viewport有时是不止一个的,需要改造引擎支持多个viewport

image-20230802161611838

14.1.1.2 可编辑游戏对象

image-20230802161933727

image-20230802162112343

  • 由对象的属性,反射出的一个schema,可以直接修改对象的属性

image-20230802162321862

14.1.1.3 内容浏览器

  • 资产不一定是在本地,也可能是在数据库
  • 内容浏览器负责将所有的资产显示到引擎中,从而不需要专门去某个静态文件夹中找

将静态文件夹转化为内容的ocean

image-20230802162456550

14.1.1.4 总结

image-20230802162953875

14.1.2 鼠标选取

Ray Casting:通过射线检测,与物体的包围盒碰撞,表示选取哪个物体

  • 透明物是不写入depth buffer的,需要特殊处理:如在particle的发生器处添加一个虚拟物体

RTT(run time type):专门绘制一个选取帧,表示每一个像素对应的物体

image-20230802163052990

14.1.3 编辑物体的 Transform

需要支持很多特性,而不是仅仅的一个transform

  • 如旋转角度的对齐

14.1.4 地形

image-20230802163900330

高度刷:

  • 重点是平滑过渡

  • 自定义笔刷:支持导入高度图,要有可扩展性

image-20230802163943757

实例刷:

  • 大面积刷树、草等物体时常用
  • 需要能够一个一个修改

image-20230802164142885

14.1.5 环境

image-20230802164329502

14.1.6 环境编辑中的规则系统

image-20230802164429700

image-20230803101518507

14.2 编辑器插件架构

14.2.1 系统&对象矩阵结构

  • plugin即需要能够修改系统,也需要能够修改单个对象

image-20230803101944704

14.2.2 多个plugin之间的组合

  • Covered:新的plugin覆盖旧的plugin
  • Distributed:不同plugin之间互不影响,最后将结果合成,产生最终输出
  • Pipeline:不同plugin依次进行加工
  • Onion rings:不同plugin之间会进行数据传输

image-20230803102307980

image-20230803102436703

14.2.3 Plugin & engine 的版本控制

  • 对引擎的接口进行版本编号,只有当接口的版本相同时,Plugin才有效

image-20230803102744948

14.3 设计叙事工具 Narrative Tools

14.3.1 游戏引擎中的叙事

  • 在时间轴上,让游戏对象动起来

image-20230803105711305

  • 示例:UE中的Sequencer

image-20230803105738398

14.4 反射和游戏逻辑

image-20230803110424118

  • 反射的任务:将代码中的接口,显示到可视化编程脚本中

14.4.1 反射

  • 反射:当写完一行代码后,系统会告诉我到底有哪些新的功能被暴露出来,从而让其他编写者在不需要重新编译这个文件的同时,使用这些新的功能的接口
  • 反射构建了代码和工具之间的桥梁

image-20230803110826742

image-20230803111124025

14.4.2 在C++中的反射实现

14.4.2.1 从代码中获取类型信息

  • 语言经过编译器生成AST后,可以在AST中很容易的得到类型信息

image-20230803111434201

image-20230803111511388

14.4.2.2 Picolo使用的是Clang

image-20230803111638570

14.4.2.3 从AST中生成Schema

image-20230803111702820

14.4.2.4 反射中的精确控制

image-20230803111731150

image-20230803111835118

14.4.2.5 反射Accessor

  • 对每个收集到的字段,生成三类方法:get, set, invoke

image-20230803112047326

14.4.2.6 代码渲染

  • 大量减少冗余代码的开发
  • 经过一次debug后,基本不会出错
  • 将数据和逻辑进行分离

image-20230803112128910

image-20230803112207954

image-20230803112325199

image-20230803112348460

14.5 协同编辑

14.5.1 解决合并时的冲突

image-20230803112656855

image-20230803112716987

将物体进行划分

  • 将世界进行分层:
    • 优点:正确的分层可以降低编辑冲突,分层有逻辑上的可行性
    • 缺点:分层难以分好,且不同层之间会有依赖
  • 对世界进行划分,分为不同地块
    • 优点:便于动态扩展世界
    • 缺点:难以处理跨界的物体
  • OFPA:每个Actor一个文件,每个人只修改自己的文件
    • 缺点:会生成很多小文件,cooking的时候需要将这些小文件打包到同一个关卡中

image-20230803112738102

image-20230803113002421

image-20230803113135835

image-20230803113155734

14.5.2 同时编辑同一个对象

image-20230803113356599

  • 基础:对编辑操作进行原子化操作,同步command

image-20230803113412177

image-20230803113555546

  • 实例锁

image-20230803113609346

  • 资源锁

image-20230803113622754

image-20230803113715453

image-20230803113723244

14.5.3 现代编辑工作流

  • 将所有的操作先同步到一个server上,然后再由server更新数据
  • server要求很高的鲁棒性

image-20230803113830069

image-20230803113948347