组件创建
要创建新组件,在开始在渲染器中编写它们之前,我们需要先做几件事。你需要遵循一个分步指南。我会列出所有步骤,然后你可以通过更详细的说明逐步执行。
在以下位置创建 proto 定义: @dcl/protocol
在以下位置生成新的 proto TypeScript 代码: js-sdk-toolchain
为以下内容创建测试:
js-sdk-toolchain在项目中生成新的 proto C# 代码
编写新组件的代码
确保该组件遵循约定
在以下位置创建 proto 定义: @dcl/protocol
要创建定义,你必须前往这个仓库:https://github.com/decentraland/protocol
在这个文件夹中创建 proto 定义:https://github.com/decentraland/protocol/tree/main/ecs/components
创建一个包含这些新更改的 PR
注意: 创建 PR 后,GitHub Bot 会评论并提供用于测试 PR 的包链接。你可以在后续步骤中使用该链接进行测试
需要考虑的事项
我们使用的是 proto 3,因此 proto 的所有定义都必须按照其 语法
我们有一些不能被重新创建的公共类型
proto 应该具备基本定义
你必须添加以下代码来枚举该组件
proto 示例
在以下位置生成新的 proto TypeScript 代码: js-sdk-toolchain
下载以下仓库:https://github.com/decentraland/js-sdk-toolchain
在其中,进入 packages/dcl/ecs (https://github.com/decentraland/js-sdk-toolchain/tree/main/packages/%40dcl/ecs)
然后,你可以执行
或者使用 GitHub Bot 在你的 @dcl/protocol PR 中生成的命令(这必须是临时的,用于测试 PR)。
然后在以下位置的根目录下运行这些命令: js-sdk-toolchain 项目:
并推送生成的代码。
在项目中生成新的 proto C# 代码
要生成 C# 代码,我们需要前往 protocol-gen 路径,在以下仓库的根目录中: @decentraland/unity-renderer 仓库。并执行以下命令:
要升级到最新版本的 @dcl/protocol (main 分支),我们应该使用
要测试 PR,我们可以使用 GitHub Bot 在以下位置生成的 URL: @dcl/protocol PR:示例:
在合并 @dcl/protocol PR 之后,我们必须使用 @dcl/protocol@next 并生成代码。
编写新组件的代码
现在是实现新组件功能的时候了。
组件有五个基本部分。
ComponentID 组件将使用的 ID。它必须是唯一的,并由 proto 定义生成
Model 这是组件的模型。这是我们用于处理组件的数据。它是通过 proto 生成自动创建的,名称与 proto 文件相同,只是在前面加上 PB。例如,如果你有一个
BoxShape.proto定义,那么生成的模型类将是PBBoxShapeComponent Handler 组件处理器将管理组件的所有功能。在这个类中,你必须实现
IECSComponentHandler<ModelClass>(ModelClass 是模型。它是从 proto 生成的类,名称将是 PB + .proto 文件名)。这个接口有 3 个重要方法需要实现,以便创建一个组件
Serializer 每个组件都负责实现其序列化和反序列化。这个序列化器必须能够将其序列化/反序列化为字节数组
Register 这将把组件注册到系统中,使其连接到系统。这个注册将把组件注册到工厂和组件写入器中
组件的设计是为了避免继承,因此我们鼓励尽可能使用纯函数
为了创建它们,我们必须遵循以下步骤
创建组件文件夹和程序集。我们所有的组件都位于以下文件夹下
DCLPlugins/ECS7/ECSComponents。你需要创建一个文件夹和一个新的程序集来承载该组件在新的程序集里,你必须引用以下内容
DCL.ECSComponents.Data。这将引用你刚刚更新的组件的新模型你必须创建带有所有逻辑的组件处理器(请查看
ECSBoxShapeComponentHandler.cs作为示例)你必须创建序列化器类(也许你可以从另一个类复制并适配到你的)
你必须创建注册类
将新的注册添加到
ECS7ComponentsComposer类中,并使用其对应的 ID
现在你的组件已经添加并可以工作了!
确保该组件遵循约定
在开发新组件时,有一些检查清单需要考虑,这部分试图对它们进行总结。
单元测试 所有组件都必须包含单元测试,至少覆盖其功能、释放以及序列化/反序列化,以确保组件能够正常工作
要考虑当组件不在场景中时会发生什么(查看
SceneBoundariesChecker类以获取更多信息)如果组件在世界中渲染某些内容,它必须将可渲染信息添加到数据存储中,这样我们就能把渲染器的信息添加到场景中,从而计入限制
如果组件在世界中渲染某些内容,它必须添加
MeshesInfo到实体中它必须尽可能高效。此代码会被执行很多次,因此我们需要确保一切尽可能流畅地运行
它必须与
热重载在预览模式下配合工作。如果你已经正确编写了OnComponentRemoved,这将开箱即用,但热重载是一种测试一切是否能与组件释放良好配合的方法如果组件使用了资源,你必须使用一个
AssetPromiseKeeper来实现资源管理。组件应在资源被使用时以及不再使用时通知AssetPromiseKeeper它
最后更新于