下午2:26
下面是一份系统性、全面的 O3DE(Open 3D Engine)插件开发指南,覆盖概念、体系结构、准备工作、详细步骤、示例、关键要点、常见问题、测试与发布、版本兼容与规范建议等。内容以“从零到可用”的路径组织,既适合入门,也可作为实施清单与参考。
—
一、基础认知与术语对齐
- O3DE 插件的本质
- O3DE 使用 C++ 组件化架构,核心扩展单元通常称为 Gem。Gem 可包含引擎扩展(反射类、系统组件、编辑器插件)、资源、脚本、UI、工具链等。Gem 既可在运行时扩展游戏功能,也可在编辑器中扩展工具。
- 除 Gem 外,常见扩展形态还有 Python 工具脚本(编辑器自动化/命令)、Prefab/Asset Pipeline 扩展、Project Template、External Submodule 等。
- 插件分类与适用场景
- Runtime 功能 Gem:提供游戏运行时功能(系统组件、模块、内存分配器、网络/物理/AI 等)。
- Editor 扩展 Gem:在 O3DE Editor 中新增面板、菜单、工具栏、操作命令、资产导入器、属性编辑器自定义控件。
- Asset Pipeline 扩展:如 Scene Processing Rules、Builder,扩展资源导入转换流程。
- Script 扩展:Ebus/BehaviorContext 暴露给 Lua/Python/Script Canvas。
- Integration/Bridge:与第三方 SDK/服务对接(广告、分析、平台、渲染后端等)。
- 关键概念
- Gems.json:描述 Gem 的元数据(名称、UUID、版本、依赖、平台、可选特性)。
- Module/Component:C++ 模块定义(AZ::Module),系统组件(AZ::Component)作为服务单元;编辑器组件常派生 EditorComponent。
- Reflection:SerializeContext、BehaviorContext、EditContext,用于序列化、脚本绑定和编辑器 UI。
- EBus:解耦通信总线。可定义 Request/Notification/Handler。
- Build/Pack:基于 CMake 和 PAL(Platform Abstraction Layer)进行多平台编译与条件编译。
- Project 与 Engine 绑定:通过 o3de CLI 将 Gem 关联到工程或全局引擎注册。
—
二、准备工作与环境搭建
- 系统与依赖
- 支持平台:Windows(VS 2019/2022 + CMake + Ninja)、Linux(Clang/GCC + CMake + Ninja)。安装 Python 3.7+(O3DE 自带)、CMake(建议与 O3DE 版本对应),Git。
- 获取源代码:克隆 O3DE 源码或下载 SDK。建议通过源代码构建以便调试引擎层。
- 安装与编译
- 配置引擎:
- Windows: cmake -B build/windows -S . -G "Ninja Multi-Config" -DLY_VERSION_ENGINE_NAME=O3DE
- Linux: cmake -B build/linux -S . -G Ninja
- 首次构建 Editor 和 Project Manager 以确认环境正常。
- 可选:注册引擎与项目
- scripts/o3de.sh/o3de.bat register --this-engine
- o3de.exe/o3de.py 创建或导入项目
- 配置引擎:
- 工具链
- IDE:Visual Studio、VS Code、CLion。安装 C++20 支持。
- Python:用于编辑器自动化、生成脚本、Asset Processor 扩展。
- 调试:VS 调试器 / lldb / gdb;RenderDoc(渲染)、RHI/RPI 控制台;Asset Processor 面板。
—
三、总体开发流程(从零开始)
- 规划插件类型与边界
- 明确插件是 Runtime 功能、Editor 工具、资源导入器还是混合。
- 列出外部依赖、需要暴露的 API(EBus/Behavior)、跨平台支持范围。
- 创建 Gem 骨架
- 使用 CLI:
- Windows: scripts/o3de.bat create-gem -g MyAwesomeGem
- Linux: scripts/o3de.sh create-gem -g MyAwesomeGem
- 选择模板(默认、Tool、AssetBuilder 等);生成目录结构:
- Gems/MyAwesomeGem/gem.json
- Code/Include, Code/Source
- Assets/, Registry/, Tools/, Scripts/ 等
- 使用 CLI:
- 配置 gem.json
- 关键字段:
- "gem_name", "display_name", "uuid", "version", "summary", "license", "origin"
- "dependencies": 依赖其他 Gems
- "link_type": "dynamic"|"static"
- "requirements": 平台/规格限制
- "user_tags": ["Editor", "Runtime", "AssetBuilder"]
- 示例片段:
- "dependencies": [{ "uuid": "xxxxxxxx-xxxx-....", "version_constraints": ">=1.0.0" }]
- 关键字段:
- CMake 集成
- CMakeLists.txt 中:
- ly_add_target(NAME MyAwesomeGem.Static NAMESPACE Gem TARGET_FILES_CXX ...)
- target_link_libraries(... PRIVATE AZ::AzCore AZ::AzFramework ...)
- 通过 PAL 宏控制平台:ly_set_target_properties(TARGET MyAwesomeGem.Static WINDOWS TRUE LINUX TRUE)
- 若含编辑器模块,添加 MyAwesomeGem.Editor 模块与 BUILD_DEPENDENCIES。
- CMakeLists.txt 中:
- 模块与系统组件
- 定义 Module:
- class MyAwesomeGemModule : public AZ::Module { AZ_MODULE_CLASS(...); }
- 提供 GetRequiredSystemComponents() 返回系统组件类型 ID。
- 定义 SystemComponent:
- 继承 AZ::Component,重写 Activate/Deactivate,提供服务声明:GetProvidedServices/GetRequiredServices。
- 在 Reflect 中注册数据结构、EBus、脚本暴露。
- 定义 Module:
- 编辑器扩展(可选)
- 定义 Editor 系统组件和/或 Editor 组件,注册到编辑器模块。
- 集成 Qt 面板:
- 使用 AzToolsFramework、QDockWidget;通过 EditorMainWindow 添加菜单和面板。
- EditContext:定义属性、UI 控件(滑条、下拉、多选、行编辑、按钮)。
- EBus 和脚本绑定
- 定义 Request/Notification Bus:
- struct MyRequests : AZ::EBusTraits { virtual void DoThing(...) = 0; };
- using MyRequestBus = AZ::EBus;
- BehaviorContext 暴露:
- bc->Class("MyService")
->Method("DoThing", &MyService::DoThing);
- bc->Class("MyService")
- Script Canvas:在 BehaviorContext 注册后自动可见。
- 定义 Request/Notification Bus:
- 资源与资产管线(可选)
- 自定义 AssetBuilder:
- 继承 AssetBuilderSDK::AssetBuilderCommandBus::Handler
- 注册 patterns 与 JobDescriptor
- 处理 CreateJobs/ProcessJob
- SceneAPI 规则与处理器:对 DCC 资源(FBX/GLTF)导入规则扩展。
- 自定义 AssetBuilder:
- 集成到项目
- 通过 Project Manager 或 CLI:
- o3de.py/o3de.exe register -gp Gems/MyAwesomeGem
- o3de.py enable-gem -gn MyAwesomeGem -pp
- 在项目的 CMake 生成构建,编译 Editor/Launcher。
- 通过 Project Manager 或 CLI:
- 调试与验证
- 启动 O3DE Editor,检查 Gem 是否启用。
- 查看 Console 与 Asset Processor 日志。
- 使用 unit tests、automation tests,验证组件生命周期。
—
四、目录结构与文件清单(建议)
- gem.json:元数据/依赖/平台信息
- Code/
- Include/MyAwesomeGem/... 头文件(公共 API)
- Source/
- Module.cpp / SystemComponent.cpp
- EditorModule.cpp / EditorSystemComponent.cpp(若需要)
- Ebuses.h / Services.h
- Builders/(资产构建器)
- Tests/(单元测试)
- Assets/(默认资源、预制体、图标)
- Registry/(默认设置、编辑器布局、注册表片段)
- Tools/(命令行工具或 Python 脚本)
- Scripts/(Python 自动化、编辑器命令)
- CMakeLists.txt(目标、依赖、宏)
—
五、最小可用示例(Runtime Gem)
- 目标:实现一个简单的服务,提供“打印问候”和“加法”功能,暴露到 BehaviorContext,供 Lua/Python/Script Canvas 调用。
核心代码结构:
- gem.json 关键字段示例
- "gem_name": "HelloGem"
- "uuid": "a1b2c3d4-0000-1111-2222-333344445555"
- "version": "1.0.0"
- "display_name": "Hello Gem"
- "summary": "Simple example gem"
- "user_tags": ["Runtime"]
- "dependencies": []
- "link_type": "dynamic"
- "platforms": ["Windows", "Linux"]
- Module 与 SystemComponent 框架
// HelloGemModule.cpp
#include <AzCore/Module/Module.h>
#include <HelloGemSystemComponent.h>
namespace HelloGem
{
class HelloGemModule final
: public AZ::Module
{
public:
AZ_RTTI(HelloGemModule, "{F4A8D1A4-7F2B-4E2E-9C7E-6F2F8C0F0ABC}", AZ::Module);
AZ_CLASS_ALLOCATOR(HelloGemModule, AZ::SystemAllocator);
HelloGemModule()
{
m_descriptors.insert(m_descriptors.end(), {
HelloGemSystemComponent::CreateDescriptor()
});
}
AZ::ComponentTypeList GetRequiredSystemComponents() const override
{
return AZ::ComponentTypeList{
azrtti_typeid<HelloGemSystemComponent>()
};
}
};
}
AZ_DECLARE_MODULE_CLASS(Gem_HelloGem, HelloGem::HelloGemModule)
// HelloGemSystemComponent.h
#pragma once
#include <AzCore/Component/Component.h>
namespace HelloGem
{
class HelloGemSystemComponent
: public AZ::Component
{
public:
AZ_COMPONENT(HelloGemSystemComponent, "{9A2B5A1C-5D9F-4C27-8B18-1E1C8C9A7A22}");
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
void Activate() override;
void Deactivate() override;
// Public API (也可通过 EBus 暴露)
int Add(int a, int b) const;
};
}
// HelloGemSystemComponent.cpp
#include "HelloGemSystemComponent.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Console/IConsole.h>
namespace HelloGem
{
void HelloGemSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (auto sc = azrtti_castAZ::SerializeContext*(context))
{
sc->Class<HelloGemSystemComponent, AZ::Component>()
->Version(1);
if (auto ec = sc->GetEditContext())
{
ec->Class("HelloGem System", "Demo system component")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Category, "HelloGem")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"));
}
}
if (auto bc = azrtti_castAZ::BehaviorContext*(context))
{
bc->Class("HelloGemSystem")
->Method("Add", &HelloGemSystemComponent::Add)
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common);
}
}
void HelloGemSystemComponent::GetProvidedServices(DependencyArrayType& provided)
{
provided.push_back(AZ_CRC_CE("HelloGemService"));
}
void HelloGemSystemComponent::GetIncompatibleServices(DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC_CE("HelloGemService"));
}
void HelloGemSystemComponent::GetRequiredServices(DependencyArrayType&) {}
void HelloGemSystemComponent::GetDependentServices(DependencyArrayType&) {}
void HelloGemSystemComponent::Activate()
{
AZ_Printf("HelloGem", "HelloGemSystemComponent Activated\n");
}
void HelloGemSystemComponent::Deactivate()
{
AZ_Printf("HelloGem", "HelloGemSystemComponent Deactivated\n");
}
int HelloGemSystemComponent::Add(int a, int b) const
{
return a + b;
}
}
- CMakeLists.txt 关键片段
ly_add_target(
NAME Gem.HelloGem STATIC
NAMESPACE Gem
FILES_CMAKE
hello_gem_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
.
BUILD_DEPENDENCIES
PRIVATE
AZ::AzCore
AZ::AzFramework
)
ly_add_target(
NAME Gem.HelloGem.Standalone MODULE
NAMESPACE Gem
OUTPUT_NAME Gem.HelloGem
BUILD_DEPENDENCIES
PRIVATE
Gem::HelloGem
)
ly_create_alias(NAME HelloGem.Clients NAMESPACE Gem TARGETS Gem.HelloGem.Standalone)
注意:实际工程中会使用模板生成的文件集和别名;确保目标被项目的 Launcher/Editor 依赖。
- 启用与测试
- 启用 Gem:o3de.py enable-gem -gn HelloGem -pp
- 构建并运行 Editor;在 Console 或 Python 控制台中:
- from azlmbr import HelloGemSystem
- obj = HelloGemSystem()
- print(obj.Add(3, 4)) # 7
—
六、编辑器扩展示例(带 Qt 面板)
目标:在 Editor 中添加一个“Hello 面板”,有一个按钮能调用系统组件的 Add,并展示结果。
要点概述:
- 定义 EditorSystemComponent,注册菜单与面板命令。
- 使用 AzToolsFramework::ActionManagerInterface 注册菜单项。
- 创建一个 QDockWidget,嵌入自定义 QWidget。
关键步骤(概览):
- EditorModule.cpp 中在构造插入 EditorSystemComponent 描述符。
- 在 EditorSystemComponent::Activate 中注册动作、创建 Dock。
- 通过 Bus 与 Runtime System 通信或直接调用共享逻辑。
提示:完整 Qt 代码略长,实际实现时参考 AzToolsFramework 示例(例如 AtomLyIntegration、ScriptCanvasEditor 的注册模式)。
—
七、资产构建器(AssetBuilder)扩展示例(概念)
场景:自定义 .foo 文本文件,生成 .azasset。
步骤:
- 注册 Builder Descriptor:名称、版本、patterns("*.foo")、BusId。
- CreateJobs:为每个 .foo 生成一个 Job(每平台一次),指定输出产品扩展。
- ProcessJob:读取 .foo,转换为二进制数据,写入输出产品目录,填充 JobProduct。
- 在 gem.json 中为 "AssetBuilder" 添加 user_tags,并确保在 Editor 启动时 Asset Processor 能加载该 Builder。
—
八、关键要点与开发规范
- 版本与兼容
- 指定 gem.json 的 "version",采用语义化版本(MAJOR.MINOR.PATCH)。
- 在 O3DE 升级时,留意 AzCore/AzFramework API 变化、CMake 宏调整、RHI/RPI 变动。
- 在 Reflect Version 变更时提供版本迁移(SerializeContext Version 与版迁器)。
- 代码质量
- 严格使用 AZ_RTTI、AZ_CLASS_ALLOCATOR;避免 new/delete,使用 AZStd::unique_ptr/IntrusivePtr。
- 明确组件服务依赖,避免循环依赖;用 Requires/Dependent Services 表达约束。
- EBus 使用:高频调用避免 EBus 带来的虚调用开销,可用 Direct API 或 Event/Handler 缓存。
- 脚本与工具
- BehaviorContext 命名清晰,方法注释;避免暴露未稳定 API。
- Python 工具使用 azlmbr API;脚本放在 Scripts/ 并在 Tools/Registry 注册到菜单。
- 平台与构建
- 使用 PAL 宏 AZ_TRAIT_XXX 控制平台特性。
- 外部第三方库通过 3rdParty 集成,注意静/动态链接许可证与发布体积。
- 性能与内存
- 使用 AZ::Interface 提供服务定位器式访问。
- 使用 AZ_PROFILE_FUNCTION/AZ_TracePrintf 进行性能与日志。
- 资源与数据驱动
- 用 Registry 默认设置暴露可调参数;使用 CVAR(AZ_CVAR)提供运行时调优。
—
九、测试、CI 与发布
- 单元测试
- 使用 GoogleTest 集成:ly_add_googletest;覆盖组件逻辑、数据转换。
- 对 BehaviorContext 绑定的 smoke test(确认方法可被调用)。
- 自动化与编辑器测试
- Python 测试脚本驱动 Editor:启动、加载关卡、调用你的工具命令,校验结果/日志。
- Asset Processor 测试:投递输入资源,验证产物生成。
- 静态检查与格式化
- clang-tidy、cpplint;统一格式(.clang-format 与 O3DE 默认)。
- CI
- 配置 GitHub Actions/Azure Pipelines:多平台构建、单元测试、打包 Gem 工件(.zip)。
- 打包与分发
- 清单:gem.json、LICENSE、README、CHANGELOG、Docs/、Code/、Assets/、Registry/、CMakeLists.txt。
- 通过 o3de 清单注册(o3de_manifest.json),允许他人 o3de.exe/o3de.py register -gp 拉取。
- 提供示例项目或最小关卡,降低集成门槛。
—
十、常见问题与排错
- Gem 未出现在项目启用列表
- 检查 gem.json 路径与 UUID;是否已 register -gp;是否满足平台要求。
- 编译错误:未找到目标/库
- CMake 目标未创建或别名未与 Editor/Launcher 链接;检查 ly_create_alias 与 BUILD_DEPENDENCIES。
- BehaviorContext 未见到类/方法
- Reflect 未被调用:确保 SystemComponent/Module 注册到描述符集合;确认编辑器/运行时加载了模块。
- Editor 崩溃/空白面板
- Qt 线程问题:UI 操作需在主线程;使用主线程调度器。
- AssetBuilder 不工作
- 未在 Builder Bus 注册或 patterns 配置不匹配;查看 Asset Processor 日志与 cache。
—
十一、实施清单(Checklist)
- 元数据
- gem.json 完整、UUID 唯一、版本语义化、依赖列表准确。
- 架构
- Module + SystemComponent 完整;服务声明齐全;Reflect 覆盖 Serialize/Behavior/Edit。
- 构建
- CMake 目标正确定义;平台宏设置;第三方库处理。
- 脚本与工具
- Python 命令可运行;ActionManager 菜单项显示;文档说明。
- 测试
- 单元测试、脚本测试、Asset Processor 测试通过;性能热点分析。
- 文档
- README、使用指南、API 示例、变更记录。
- 发布
- 打包、校验 LICENSE、兼容 O3DE 版本说明、示例工程。
—
十二、进阶主题与实践建议
- 多模块 Gem 切分:将 Runtime/Editor/Builders 拆分为独立 target,减少链接体积与依赖耦合。
- 数据驱动配置:在 Registry 提供默认 CVAR/设置,允许用户覆盖。
- 热重载与开发效率:利用 Editor 的 Python 控制台和工具菜单实现快速迭代。
- 可观测性:集成 ImGui/Telemetry(遵循许可)或使用 O3DE Profiler 与 AZ::Metrics。
- 跨平台资源路径与文件系统:使用 AZ::IO::FileIOBase 和 PathView,避免平台差异。
- 安全与稳定:对外部输入做校验;避免未经限制的脚本执行;注意线程安全(EBus Handler 在 Activate/Deactivate 生命周期内注册/注销)。
—
十三、示例 Gem 方向建议(可作为模板起点)
- Gameplay Utilities:时间轴、状态机(BehaviorContext 暴露)。
- Networking Helper:HTTP/GRPC 客户端(封装 curl/Protobuf)。
- Editor Productivity:批量重命名、批量材质替换、资源清理。
- Asset Import:定制格式导入,生成自定义组件资源。
- Analytics/Telemetry:事件上报与离线缓存。
—
十四、规格与文档模板建议
- 规格说明书(SRS)要点
- 背景与目标
- 功能列表(用例、输入输出、错误码)
- 非功能需求(性能、内存、平台、可扩展性、安全)
- 接口规范(EBus/Behavior API、CVAR、配置文件结构)
- 资源规格(资产扩展名、构建产物、缓存策略)
- 兼容性矩阵(O3DE 版本、OS、编译器)
- 测试计划与验收标准
- 版本策略与弃用策略
- API 文档结构
- 命名空间、类清单、方法签名、参数/返回值、示例代码、注意事项。
- 变更记录:新增/修改/弃用标签。
- 代码注释规范
- Doxygen 风格注释;示例:
- @brief, @param, @return, @note, @warning
- 反射版本注释:说明字段新增/迁移逻辑。
- Doxygen 风格注释;示例:
—
结语
以上指南覆盖了 O3DE 插件(Gem)开发的完整生命周期与关键实现路径:从环境搭建、模块/组件/反射、编辑器与资产管线扩展,到测试发布与规范化管理。你可以直接据此搭建一个最小 Gem,逐步添加 Editor/AssetBuilder 能力,并按 Checklist 与规范完善工程。
如果你希望,我可以:
- 依据你的目标功能,生成一套定制的 gem.json、CMakeLists 和完整最小代码骨架。
- 为某个具体扩展(例如 Editor 面板或 AssetBuilder)提供完整的可编译样例。
- 根据你的团队规范生成 SRS/API 文档模板与 CI 配置。
1439

被折叠的 条评论
为什么被折叠?



