# VRM 多人社交世界規畫

> 狀態：工作草案，適合逐項討論與修訂。這份文件記錄目前方向，不代表所有產品與技術決策都已定案。

**目標：** 建立一個使用者能帶入 VRM Avatar、在多人房間互動，並讓其他使用者看見其 VRMA 特殊動作的瀏覽器 MMO 原型。

**架構：** 瀏覽器負責 3D 場景、VRM 顯示和 VRMA 播放；PHP/OpenSwoole 提供 HTTP API 與 WebSocket 即時服務；資料庫保存帳號、資產與房間資料；Redis 管理即時房間狀態；VRM/VRMA 檔案放在物件儲存並由 CDN 傳遞。MVP 先完成小型社交房間，之後再依實測擴展。

**暫定技術：** TypeScript、Three.js、`@pixiv/three-vrm`、PHP、OpenSwoole、MariaDB、Redis、S3 相容物件儲存。MariaDB 已選定；部署方式及版本尚待確認。

---

## 1. 目前共識與暫定假設

- 核心體驗是多人同場互動，而非單人 VRM 檢視器。
- 使用者可以上傳自己的 VRM，並讓其他玩家看見。
- 使用者可以上傳自訂 VRMA 特殊動作，並在房間中觸發。
- 3D 模型與動畫由各使用者的瀏覽器載入、播放；即時伺服器傳遞狀態和動作事件。
- 登入前使用輕量網頁畫面，可加入可愛、低負擔的小動畫；完整 3D 場景與 VRM 登入後才載入。
- 第一個可驗證版本暫以桌面瀏覽器為目標。是否納入 VR 頭戴裝置仍未決定。
- 初期房間人數、更新頻率和檔案限制是測試目標，不能先視為容量承諾。
- 目前工作區沒有既有應用程式程式碼；實作時再依專案骨架確定目錄與檔案名稱。

## 2. MVP 範圍

### 包含

- 使用者登入與基本個人資料。
- 上傳 VRM、選擇自己的 Avatar，並在場景中顯示。
- 建立或加入一個多人房間，顯示其他在線玩家。
- 基本位置、朝向同步與平滑顯示。
- 上傳或選取 VRMA，觸發後讓房間內其他玩家看到相同動作。
- 晚加入的玩家收到目前房間狀態；若動作仍在播放，從正確進度呈現。
- 以檔案狀態管理上傳流程，驗證通過後才提供其他使用者下載。

### 登入與進入世界流程

```text
輕量登入頁（插圖或小角色動畫）
  → 登入成功
  → 顯示進入世界的載入狀態
  → 載入 3D 場景與使用者 VRM
  → 取得 WebSocket ticket 並加入房間
  → 顯示多人世界
```

登入頁不初始化完整 3D 世界，也不預先下載使用者 VRM，以保持首次載入輕快。可愛動畫可先探索角色眨眼、輕微漂浮或揮手等小動作；這些是視覺方向範例，角色造型和動畫形式之後再定。動畫應保持克制，並尊重瀏覽器的減少動態偏好。

### 暫不納入

- VR 頭戴裝置與手部追蹤。
- 未登入即可進入完整 3D 大廳。
- 內建骨骼關鍵影格動作編輯器；初版先上傳 VRMA。
- 語音聊天、交易、道具、任務、公會或大型戰鬥系統。
- 任意腳本、外掛或使用者 shader。
- 多區域世界與跨服無縫移動。

## 3. 系統關係

```mermaid
flowchart LR
    C[瀏覽器遊戲客戶端\nThree.js + VRM/VRMA] -->|HTTPS API| API[PHP / OpenSwoole HTTP]
    C <-->|WebSocket 狀態與事件| WS[PHP / OpenSwoole WebSocket]
    API --> DB[(MariaDB)]
    API --> R[(Redis)]
    WS --> R
    API -->|簽發短效上傳/下載 URL| O[(S3 相容物件儲存)]
    C -->|直接上傳/下載大型檔案| O
    O --> CDN[CDN]
    C --> CDN
    API --> Q[背景驗證工作佇列]
    Q --> O
    Q --> DB
```

責任邊界：

- **瀏覽器客戶端：** 場景渲染、VRM/VRMA 載入、動畫播放、輸入處理、插值，以及畫面效能控制。
- **HTTP API：** 認證、資產與 Avatar 管理、房間清單、短效上傳/下載授權。
- **WebSocket 服務：** 連線驗證、房間加入/離開、玩家狀態與動作事件廣播。
- **MariaDB：** 持久化使用者、資產中繼資料、Avatar 選擇、房間設定及審核狀態。
- **Redis：** 在線連線、房間即時狀態、短期快取及多個即時服務實例間的訊息傳遞。
- **物件儲存/CDN：** 保存與傳遞 VRM、VRMA、縮圖等大型檔案，不把檔案本體塞進 WebSocket 或資料庫。
- **背景驗證工作：** 檢查格式、規格版本、資產預算與授權中繼資料，成功後才將資產設為可使用。

## 4. 即時同步草案

伺服器保存房間內權威狀態，客戶端送出輸入或意圖；伺服器驗證後更新狀態並廣播。各客戶端用插值保持流暢畫面。MVP 可先用約每秒 10–20 次的狀態更新做實測，再根據流量與延遲調整。

VRMA 以動作事件同步，不逐幀傳送骨骼：

```json
{
  "type": "action.play",
  "actorId": "user_123",
  "animationId": "anim_456",
  "startedAt": 1720000000123,
  "loop": false,
  "sequence": 42
}
```

接收端以伺服器時間 `startedAt` 算出動畫進度並本地播放。房間快照需包含玩家 Avatar、位置、朝向與目前動作狀態，避免晚加入者只能看到空房間或動作從頭重播。

第一版訊息草案：

| 方向 | 訊息 | 用途 |
|---|---|---|
| Client → Server | `hello` | 使用短效 ticket 建立已認證連線 |
| Client → Server | `room.join` | 加入指定房間 |
| Client → Server | `input.move` | 傳送移動意圖 |
| Client → Server | `action.play` | 要求播放已授權的動作資產 |
| Client → Server | `heartbeat` | 維持連線並確認活躍狀態 |
| Server → Client | `room.snapshot` | 初次加入時傳送房間完整狀態 |
| Server → Client | `entity.join/update/leave` | 玩家進出與狀態更新 |
| Server → Client | `action.play` | 廣播已接受的動作及其伺服器開始時間 |
| Server → Client | `error` | 回傳一致格式的協定錯誤 |

所有訊息都需驗證類型、欄位、大小與頻率；客戶端提供的使用者 ID、時間與資產擁有權不能直接信任。

## 5. HTTP API 草案

API 使用一致的 JSON 錯誤結構，清單端點使用分頁；資產 ID、擁有權及狀態由伺服器判定。

| 方法 | 路徑 | 用途 |
|---|---|---|
| `POST` | `/api/auth/login` | 登入並取得 API 認證 |
| `POST` | `/api/assets/upload-sessions` | 建立 VRM 或 VRMA 上傳工作並取得短效 URL |
| `POST` | `/api/assets/{id}/complete` | 通知上傳完成，開始背景驗證 |
| `GET` | `/api/assets/{id}` | 查詢資產狀態與安全中繼資料 |
| `GET` | `/api/avatars` | 列出目前使用者可用的 Avatar |
| `POST` | `/api/avatars` | 建立 Avatar 設定並關聯 VRM 資產 |
| `GET` | `/api/rooms` | 列出可加入房間 |
| `POST` | `/api/rooms/{id}/join-ticket` | 取得短效 WebSocket 房間 ticket |
| `WS` | `/ws` | 即時房間連線；ticket 不放在長效憑證欄位中 |

統一錯誤格式示例：

```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid VRMA file",
    "details": {}
  }
}
```

## 6. 資料模型草案

### 本機開發資料庫連線

- 資料庫：MariaDB
- Host：`localhost`
- Port：`3306`
- Database：`mmo`
- Username：`mmo`
- Password：由本機未追蹤的 `.env` 提供，不寫入本計畫或版本控制。

本機環境變數可採用 `DB_HOST`、`DB_PORT`、`DB_DATABASE`、`DB_USERNAME`、`DB_PASSWORD`。使用者提供的密碼僅供本機開發，因為強度較低，不可用於對外服務或正式環境；正式環境需使用獨立、強度足夠的密碼或密鑰管理服務。

- `users`：帳號、暱稱與狀態。
- `assets`：擁有者、類型（VRM/VRMA）、物件儲存 key、雜湊、大小、規格版本、驗證狀態與中繼資料。
- `avatars`：使用者建立的 Avatar 設定及其 VRM 資產關聯。
- `rooms`：房間名稱、容量、可見性與設定。
- `room_members`：可持久化的房間成員關係；即時在線狀態保留在 Redis。

若日後需要版本管理、分享權限、收藏、動作預設或審核紀錄，再依實際需求新增表，不預先擴張 MVP schema。

## 7. 上傳與資產發布流程

1. 客戶端向 API 建立上傳工作；伺服器檢查使用者權限並回傳短效、限定檔案用途的 URL。
2. 客戶端直接把檔案上傳到隔離中的物件儲存位置。
3. 客戶端呼叫完成端點；伺服器將資產標示為 `PROCESSING` 並排入背景工作。
4. 背景工作驗證真實格式、VRM/VRMA 規格、中繼資料、檔案大小、貼圖、網格、骨骼、動畫長度及允許的 glTF extension。
5. 驗證成功後產生或確認縮圖，資產進入 `READY` 並可取得 CDN URL；失敗則進入 `REJECTED` 並保存可供使用者理解的錯誤原因。

資產至少使用 `PENDING_UPLOAD`、`PROCESSING`、`READY`、`REJECTED`、`DISABLED` 狀態。具體檔案與複雜度上限、掃描方式、保留政策和審核流程仍待產品需求決定。

VRM 可能包含作者、署名與使用限制等資訊。系統應解析、呈現並保存相關中繼資料；使用者上傳不代表取得模型或動作的著作權。

## 8. 分階段工作與驗收條件

### Phase 0：技術驗證

先證明 VRM、VRMA 與多人事件同步可在選定的客戶端組合中共同運作。

- 初步測試模型：`VRM/Alicia/VRM/AliciaSolid.vrm`（Alicia Solid，VRM 0.x，約 7.9 MB；檔案中作者標記為 © DWANGO Co., Ltd.）。先確認載入及基本場景移動，再擴展到動畫和多人同步；若公開展示，先確認模型授權條件。
- 單機移動原型：`prototype-vrm.html`，以 Three.js 與 `@pixiv/three-vrm` 載入此模型，在程式生成的地板上用 WASD／方向鍵移動，R 回到起點。這是短期技術驗證，不含登入、後端、多人同步或步態動畫；執行方式見 `prototype-vrm-README.md`。
- 客戶端能載入目標範圍內的 VRM，並正確顯示模型。
- 客戶端能載入 VRMA，套用到 VRM 並播放。
- 兩個瀏覽器客戶端可連上 OpenSwoole WebSocket，同房看到彼此的基本狀態。
- A 觸發動作後，B 播放相同資產並依伺服器開始時間對齊進度。
- B 中途加入時取得目前狀態；若動作仍在播放，顯示接近正確進度。
- 記錄載入失敗類型、兩端延遲及基本瀏覽器效能，據此確定格式支援政策。

### Phase 1：最小多人流程

- 使用者可登入、上傳 VRM、選用 Avatar、加入房間並看到其他玩家。
- 玩家移動和朝向會同步，斷線後不會永久留在房間。
- 使用者可上傳 VRMA，通過驗證後觸發；其他玩家能看見該動作。
- 未通過驗證的檔案不會被房間或公開資產 API 發布。
- 以端到端手動流程驗收：登入 → 上傳 → 加入 → 互見 → 播放動作。

### Checkpoint：核心體驗

- 兩個以上瀏覽器客戶端完成 Phase 1 流程。
- 驗證一般網路延遲、重新連線、無效資產與同時觸發動作的行為。
- 根據測試結果決定房間容量、移動更新頻率、檔案限制及 VRM 版本支援範圍。

### Phase 2：資產管理與社群基本治理

- 提供資產列表、替換/刪除、公開性及作者署名資訊。
- 提供舉報與管理員下架流程。
- 顯示清楚的檔案失敗原因，並限制重試與資源消耗。
- 對上傳、下載、API 與 WebSocket 訊息套用權限和頻率限制。

### Phase 3：房間擴展與可靠性

- Redis 管理跨 OpenSwoole worker/實例的房間事件與在線狀態。
- 以房間為單位分片或路由，並只對需要接收的玩家廣播狀態。
- 加入 WebSocket 重連、狀態重新同步、服務健康監控與容量測試。
- 根據實際流量決定是否需要多區域部署或額外佇列系統。

### Phase 4：自訂動作編輯器（獨立規畫）

- 研究骨骼姿勢、關鍵影格、表情與視線軌道的編輯體驗。
- 編輯結果可預覽並匯出為標準 VRMA。
- 定義跨不同 VRM humanoid 骨架的 retarget 行為與相容性提示。

## 9. 部署方向

目前工作區環境是 Windows/Apache。OpenSwoole 官方安裝說明建議 Windows 使用 WSL 或 Docker；應先以 Docker Compose 或 WSL 建立可重現的本機服務，並在其中啟動 MariaDB，再決定正式環境部署方式。

```text
本機開發
├── Web Client：瀏覽器開發伺服器
└── Docker Compose / WSL
    ├── PHP + OpenSwoole HTTP/WebSocket
    ├── MariaDB
    ├── Redis
    └── S3 相容物件儲存（例如 MinIO）
```

正式環境預計使用 HTTPS/WSS、反向代理、TLS、資料庫備份、物件儲存生命週期政策與 CDN；供應商和成本需在目標用戶規模與預算明確後選定。

## 10. 主要風險與因應

| 風險 | 影響 | 因應方向 |
|---|---|---|
| VRM/VRMA 版本或骨架差異 | 某些 Avatar 無法載入或動作姿勢不正確 | Phase 0 建立代表性檔案測試集，之後公布明確支援範圍 |
| 大型模型影響載入與 FPS | 使用者等待過久，場景掉幀 | 背景驗證資產預算、縮圖/CDN、客戶端載入進度與效能降級策略 |
| 多個 OpenSwoole worker 的狀態不一致 | 玩家重複、狀態遺失或房間訊息漏收 | 不依賴單一 worker 記憶體保存跨連線權威狀態，使用共享狀態與明確房間路由 |
| 惡意或格式異常的 glTF 檔案 | 驗證工作或客戶端載入出錯 | 隔離上傳檔、限制資源預算、驗證 extension，僅發布 READY 資產 |
| 使用者未取得資產公開/展示授權 | 侵權申訴或下架需求 | 保存授權中繼資料、公開使用規則、提供舉報與下架程序 |
| Windows 開發環境和 Linux 部署差異 | 本機可跑、部署失敗 | 從第一個原型就用 WSL/Docker 測試 OpenSwoole 執行環境 |

## 11. 待討論決策

依賴順序建議先決定平台與核心使用體驗，再確定檔案相容性、容量及部署細節。

1. **MVP 平台：** 先做桌面瀏覽器，還是首版就要求 VR 頭戴裝置？
2. **使用模式：** 主要是自由社交房間、固定大廳，還是帶有遊戲目標的 MMO？
3. **資產版本：** 初版接受 VRM 0.x、VRM 1.0，或先限定一種？VRMA 支援範圍以 VRMA 1.0 為主嗎？
4. **房間規模：** 初期同房人數目標及畫面可接受的最低裝置規格為何？
5. **動作來源：** 初期只接受 VRMA 上傳，還是也需要內建動作庫？
6. **公開與授權：** 上傳資產預設私人、房間可見，還是公開可搜尋？
7. **部署與成本：** 是否已有伺服器、網域、物件儲存或月費上限？

## 12. 參考資料

- OpenSwoole WebSocket Server：<https://openswoole.com/docs/modules/swoole-websocket-server>
- OpenSwoole 安裝（含 Windows/WSL 建議）：<https://openswoole.com/docs/get-started/installation>
- VRM 1.0 規格：<https://github.com/vrm-c/vrm-specification/tree/master/specification/VRMC_vrm-1.0>
- VRM Animation 1.0 規格：<https://github.com/vrm-c/vrm-specification/tree/master/specification/VRMC_vrm_animation-1.0>
- VRM 授權中繼資料規格：<https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/meta.md>
- `@pixiv/three-vrm`：<https://github.com/pixiv/three-vrm>
- `three-vrm-animation` API：<https://pixiv.github.io/three-vrm/docs/modules/three-vrm-animation.html>
