快速开始
从安装到第一个可运行的任务闭环,理解 Overworld Engine 的跨平台装配方式
Overworld Engine 是一个面向生产的跨平台 3D RPG TypeScript 框架。它把世界 渲染、玩家控制、无头玩法引擎、AI、联机、UI 和多端适配拆成 27 个独立包。你只 安装需要的能力,并在应用层决定它们如何协作;同一套领域系统可以运行在 Web、 桌面、移动端、小游戏与 Node.js 服务端。
这篇指南有两条路径:
| 你的目标 | 从哪里开始 |
|---|---|
| 先确认框架实际能做什么 | 运行仓库里的 Starter,约 3 分钟看到完整垂直切片 |
| 接入已有 TypeScript 应用 | 完成一个最小闭环:移动 → 任务 → 奖励 → UI 事件 |
下面的接入示例不要求 three.js,也不要求任务包依赖场景、背包或 UI。完成后你会 得到一个可以用日志直接验收的运行时闭环。
0. 先体验完整 Starter(推荐)
如果你还没决定是否采用 Overworld,先运行真实示例,不必先理解所有包:
git clone https://github.com/luzhenqian/overworld.git
cd overworld
corepack enable
pnpm install
pnpm build
pnpm --filter starter dev打开终端显示的地址,按 Starter 验收路线 依次体验移动、对话、任务、背包、AI、联机与编辑器。准备接入自己的应用时,再从 下一节开始。
前置要求
| 项目 | 当前支持范围 |
|---|---|
| JavaScript 运行时 | 现代浏览器;仓库 CI 使用 Node.js 22 |
| 模块 | ESM |
| TypeScript | strict 项目;仓库使用 TypeScript 5.6 |
| React 3D 栈 | React 18、three.js ≥ 0.160、React Three Fiber 8、drei 9 |
| 状态 | zustand 5 |
发布包不依赖 pnpm。npm、yarn 与 pnpm 都可以使用;本文命令默认采用 pnpm。 完整的 peer 依赖矩阵与多包管理器命令见兼容性与支持范围。
1. 安装最小组合
先安装 core 和需要的系统。下面的闭环使用 quest;加入 scene 才需要
React 3D peer:
pnpm add @overworld-engine/core @overworld-engine/quest react zustand如果要渲染 3D 世界:
pnpm add @overworld-engine/scene react react-dom three \
@react-three/fiber @react-three/drei zustandOverworld 没有“全家桶”入口。显式安装所需包能让依赖、包体和系统边界保持清楚。 不知道如何选择时,先看包选择指南。
2. 定义纯内容
任务标题、目标、触发事件和奖励都是可序列化数据。type 字符串只是对应用代码
中处理器的引用,不会把业务逻辑塞进内容:
import type { QuestDefinition } from '@overworld-engine/quest'
export const QUESTS: QuestDefinition[] = [
{
id: 'first-steps',
title: '迈出第一步',
description: '在村庄里走 20 米。',
autoStart: true,
objectives: [
{
id: 'walk',
description: '探索村庄',
target: 20,
trigger: {
event: 'player:moved',
amountFrom: 'distance',
},
},
],
rewards: [
{ type: 'wallet.addGold', params: { amount: 50 } },
],
},
]在真实项目里,title、description 通常保存 i18n key;参考
i18n 内容组织。
3. 在一个装配点创建引擎
注册表是声明式内容与游戏代码唯一需要相遇的地方。任务引擎只认识
wallet.addGold 这个名字,不认识你的钱包 store:
import {
createConditionRegistry,
createEffectRegistry,
gameEvents,
} from '@overworld-engine/core'
import { createQuestEngine } from '@overworld-engine/quest'
import { QUESTS } from './content'
export const conditions = createConditionRegistry()
export const effects = createEffectRegistry()
let gold = 0
effects.register('wallet.addGold', (params) => {
gold += Number(params.amount)
})
export const quests = createQuestEngine({
quests: QUESTS,
conditions,
effects,
events: gameEvents,
persist: false,
})
export function getGold() {
return gold
}persist: false 适合第一个原型。准备保存进度时显式改成 true 或传入带
name、version、migrate 与 storage 的配置;见
持久化互操作。
4. 发出领域事件
先订阅任务完成事件,再让移动系统发出类型安全的领域事件:
import { gameEvents } from '@overworld-engine/core'
import { getGold, quests } from './game/engines'
const stop = gameEvents.on('quest:completed', ({ questId }) => {
console.log(`任务完成:${questId},当前金币:${getGold()}`)
})
gameEvents.emit('player:moved', {
position: [20, 0, 0],
distance: 20,
})
// 控制台:任务完成:first-steps,当前金币:50
stop()
quests.dispose()quest 订阅了内容中声明的 player:moved,会按 amountFrom: 'distance'
累计目标。达到 20 后,它按顺序执行奖励,并发出 quest:objective-completed
与 quest:completed。这里显式清理监听器和引擎;在 React 应用中应在所属
runtime 或组件卸载时做同样的清理。
渲染世界时,scene 的 <Player> 会替你发出真实移动事件:
import { Canvas } from '@react-three/fiber'
import { Player, SceneShell } from '@overworld-engine/scene'
export function World() {
return (
<Canvas shadows>
<ambientLight intensity={1.2} />
<SceneShell
npcs={[]}
buildings={[]}
player={<Player />}
/>
</Canvas>
)
}5. 让 UI 响应,而不是反向耦合
UI 可以订阅事件,也可以直接订阅引擎的 zustand store:一次性反馈(Toast、 音效、埋点)适合事件,长期状态(任务列表、当前进度)适合 store。不要靠重放 历史事件恢复页面状态。
如果使用 @overworld-engine/ui,引擎绑定组件通过结构类型接入真实引擎,不会
让 UI 包反向依赖任务包:
import '@overworld-engine/ui/styles.css'
import '@overworld-engine/ui/themes/hextech.css'
import { QuestTracker } from '@overworld-engine/ui'
import { quests } from './game/engines'
<QuestTracker engine={quests} />6. 验证内容和接线
开发构建中,让 devtools 在内容进入运行时前检查引用、循环与未注册的条件/效果:
pnpm add -D @overworld-engine/devtools @overworld-engine/test-kitif (import.meta.env.DEV) {
const { assertValidContent } = await import('@overworld-engine/devtools')
assertValidContent(
{ quests: QUESTS },
{
effectTypes: effects.types(),
conditionTypes: conditions.types(),
},
)
}应用层测试可用 @overworld-engine/test-kit 录制真实事件流,证明装配没有漏接:
import { createEventRecorder } from '@overworld-engine/test-kit'
const recorder = createEventRecorder(gameEvents)
// 驱动真实 action 或事件……
expect(recorder.events.at(-1)?.event).toBe('quest:completed')
recorder.stop()完成标准
继续叠加系统前,先确认这个最小运行时满足:
- 触发一次 20 米移动后,控制台只出现一次任务完成日志。
- 日志中的金币为 50,说明效果先于
quest:completed事件执行。 - 调用
dispose()后继续发移动事件,不再改变任务状态。 - 内容文件没有 import wallet、UI 或 React 组件。
- 开发构建的内容校验没有未知条件、未知效果或悬空引用。
如果任一项不成立,先看排障手册,不要继续接入更多包。
下一步
| 如果你要…… | 接下来阅读 |
|---|---|
| 跑一个完整可玩项目 | Starter 示例 |
| 建立 EventBus、store、注册表的心智模型 | 核心概念 |
| 理解包边界与事件协作 | 架构说明 |
| 选择第一批依赖 | 包选择指南 |
| 构建密集 3D 世界 | 密集世界指南 |
| 接入 WebSocket / 权威服 | 权威多人 |
| 面向 Web、桌面、移动端或微信交付 | 多端支持 |
| 遇到安装、存档、输入或联机问题 | 排障手册 |
也可以直接阅读全部 27 个包的参考文档。每个参考页都以当前
packages/*/src/index.ts 的公开导出为边界。