本页尚未翻译,当前显示英文版本。
SDK 的构成
SDK 如何编写,又如何运行。 为什么同一个思路在 Python 和 Unreal C++ 中看起来略有不同,以及你的调用和网络之间隔着什么。
从一般到具体
SDK 是一套设计,有两种收窄方式,而层级顺序就是规则:只有上一层无法表达时,才会把东西下放到下一层。
| 层级 | 这一层放什么 |
|---|---|
| 通用原则 | 在每种绑定(binding)中都完全一致:行为以特 性的形式声明在它所描述的对象旁边;你推送的每一条声明(declaration),管理面板都会渲染出来;你的代码只面向模块,别无其他。 |
| 语言的形态 | 只放某种语言的范式无法按通用方式表达的内容。C# 有特性,Python 有装饰器——同一条声明,按各语言本来表达这一思路的方式来写。没有这类结构的语言,用另一种方式承载同一条声明,并在适用处明确说明这种承载方式,而不是默认读者知道。 |
| 引擎的形态 | 只放游戏引擎在其语言之上重新塑造的内容。Unreal C++ 不是普通的 C++——它有自己的对象模型和构建期反射,所以声明要放在引擎自己的反射宏里,写在这个宏原本接收说明符的位置。Unity C# 也不是服务器端的 C#:运行时更旧,基础库更小。 |
从上往下读,就明白为什么每个示例中的六个标签页并不是六套不同的 API。它们是同一套 API 的六种写法,你能看到的差异,只是下面两层透出来的部分。
如何运行:从你的代码往下
游戏代码看到的是模块,相关词汇也到此为止。
- 模块是你直接面向的对象。它们构成一张图,而不是一棵树,这样做带来的好处见 继承与组合。
- 四个原语(primitive)是组装模块的材料——事件、RPC、数据与 订阅、群组。房间、聊天和匹配池,都是同一个群组(group)原语,只是规则不同。
- hub 在下面一层,你永远不会直接调用它:依赖注入、模块挂载、用户会话、状态恢复和消息服务质量都由它负责。它只在 深入底层 中介绍一次。
- 传输适配器(transport adapter)位于最底层,每种协议一个,hub 把它们完全隐藏起来。适配器会有好几种——WebSocket、我们自己的 UDP、HTTP——由哪一种承载某次调用,你的代码既不决定,也察觉不到。
模块在投递方面告诉你的只有服务质量——至少一次,或至多一次——别无其他。底层传输可以更换,你的代码无需改动。
你能从中得到什么
- 只有一个 SDK,而不是客户端一个、服务器一个。 一次调用能做什么,取决于主体(actor)的授权,而不是某个 build 开关。详见 由谁决策。
- 声明是一切的输入。 推送声明后,带类型的 API 随即出现,管理面板渲染它,各绑定的代码生成也随之完成。参见 Schema 即代码。
- 模块靠组合,而不是继承。 具体怎么组合,以及“继承”在这里指什么,见 继承与组合。