從這裡開始
準備網頁建置,不是安裝檔
OpenGames 會在受限 iframe 中執行靜態 HTML、JavaScript、WebAssembly、媒體與字型。請從原始專案匯出 Web 版本,透過 HTTP 測試,再壓縮輸出資料夾裡面的檔案。
匯出
建立包含 index.html 的靜態瀏覽器版本。
測試
透過 HTTP 開啟,修正 Console 與 Network 的所有錯誤。
檢查並發布
先用本機轉換檢查,再壓縮根目錄內容並上傳。
my-game.zip
├─ index.html
├─ game.js
├─ game.wasm
└─ assets/
├─ sprites.webp
└─ music.oggWEB EXPORTS
從原始專案匯出
EXE、APK、IPA 或桌面安裝程式無法可靠轉換。請使用對應的原始專案與官方 Web 工具鏈。
UNITY WEBUnity C# → Web+
從 Unity 原始專案建立 Web 版本;Windows EXE 或 Android APK 不能取代原始專案。
- 在 Unity Hub 為專案使用的 Editor 版本安裝 Web Build Support。
- 建立並切換到 Web Build Profile,加入要發布的場景,關閉 Development Build。
- 移除原生 DLL、桌面檔案系統、原生 Socket,以及強制使用 SharedArrayBuffer 的套件。
- 輸出到新的空資料夾;ZIP 只包含輸出資料夾內的 index.html、Build 與資源。
C / C++ / WASMC/C++ → Emscripten+
Emscripten 重新編譯原始碼;Windows API、桌面視窗與同步檔案流程通常需要改寫。
- 安裝並啟用 emsdk;Windows 使用 Emscripten Command Prompt。
- 使用 em++ 或 emcmake 建立 Release 網頁版本,輸出檔名設為 index.html。
- 把阻塞式 while 遊戲迴圈改為 Emscripten main loop,並以 --preload-file 封裝素材。
- 透過 emrun 或本機 HTTP 伺服器測試,不要直接雙擊 HTML。
C# / .NET WASM獨立 Blazor WebAssembly+
只適用於能發布成靜態檔案的獨立 WebAssembly 專案;WinForms、WPF、MAUI 與需要 ASP.NET Server 的專案不能直接上傳。
- 確認是獨立 Blazor WebAssembly,而不是桌面 UI 或必須常駐伺服器的專案。
- 移除 Registry、本機任意檔案、原生 DLL 與伺服器端相依。
- 執行 dotnet publish -c Release。
- 從 publish/wwwroot 或 browser-wasm/publish 取出包含 index.html 與 _framework 的靜態輸出。
GODOT WEBGodot → Web+
Godot 4 的 GDScript 專案可匯出;Godot 4 C# 目前不能匯出到 Web。
- 優先使用 Compatibility renderer,移除 Web 不支援的原生外掛。
- 安裝與 Editor 同版本的 Export Templates。
- 新增 Web preset,選好主場景與資源,輸出檔名設為 index.html。
- 採用單執行緒相容建置,透過 HTTP 測試後再封裝。
# Run this inside the exported build folder.
py -m http.server 8080
# Then open http://localhost:8080 and inspect Console + Network.PACKAGE & PUBLISH
套件就是公開版本
ZIP 硬性限制
- ZIP 根目錄必須直接看到 index.html。
- 壓縮後 50 MiB、解壓後 250 MiB、最多 2,000 個檔案。
- 不能加密、巢狀壓縮,也不能含絕對路徑、上層路徑或磁碟機路徑。
- 發布後路徑區分大小寫;素材請使用相對網址。
禁止檔案
可執行檔、腳本、安裝程式、行動套件與巢狀壓縮檔會被拒絕:
exe bat cmd ps1 sh php py rb cgi jar msi scr com apk dmg pkg deb rpm zip rar 7z tarDLL 只允許位於 .NET WebAssembly 的 _framework 目錄;Gzip 只允許用於平台可辨識的 Web 建置資源。
作品資料要求
- 繁中與英文名稱皆必填,各 1–80 字元。
- 繁中與英文介紹皆必填,各 1–1,600 字元。
- 最多 8 個逗號分隔標籤;版本為 1–20 個英數字、點、底線或連字號。
- 每位創作者每天最多發布 3 個版本。
權利設定彼此獨立
作品授權、選填的原始碼網址與 ZIP 下載權限要分開設定。發布到開源平台,不代表遊戲必須開源。
發布者必須擁有發布權利,並符合全年齡社群規範。
SANDBOX CONTRACT
先確認遊戲能存取什麼
- HTML / CSS / JavaScript / WebAssembly
- 同一版本內的檔案、data: 與 blob: 資源
- 腳本、Web Worker、指標鎖定、自動播放、全螢幕與遊戲手把
- 透過 OpenGames SDK 橋接語言、帳號存檔與多人連線
- 外部 API、任意伺服器、原生 TCP/UDP 與 Socket
- 彈窗、表單、頂層導覽、瀏覽器外掛與 object 嵌入
- 相機、麥克風、定位、付款、USB、序列埠與剪貼簿
- OpenGames Cookie、Email、存取權杖與直接帳號資料
OPENGAMES SDK v1
一個橋接,不暴露帳號憑證
從平台來源載入 /opengames-sdk.js,並等待 ready()。SDK 只會在遊戲由 OpenGames 嵌入時運作;站外測試請先檢查 window.OpenGames,並提供離線行為。
| 方法 | 輸入 | 回傳 | 用途 |
|---|---|---|---|
OpenGames.ready() | — | Promise<Capabilities> | 遊戲啟動前讀取登入、語言、存檔與多人功能。 |
OpenGames.on(type, callback) | event name, callback | unsubscribe() | 監聽多人訊息或 Presence 人數事件。 |
saves.load(slot) | slot?: string | { save: Save | null } | 載入一個帳號存檔槽。 |
saves.write(data, options) | JSON data, { slot, version } | { save: Save } | 建立存檔,或檢查版本後更新。 |
saves.remove(slot) | slot?: string | { deleted: true } | 刪除一個存檔槽。 |
multiplayer.list() | — | { rooms: RoomSummary[] } | 列出這款遊戲最多 50 個公開房。 |
multiplayer.create(options) | visibility, password?, mode, teamCount? | { room: Room } | 建立玩家房或創作者房,並自動連線。 |
multiplayer.join(code, password) | 6-character code, password? | { room: Room } | 以邀請碼加入房間並自動連線。 |
multiplayer.joinGlobal(mode) | allowed mode | { room: Room } | 加入此遊戲設定的單一永久世界。 |
multiplayer.send(payload) | JSON-compatible payload | { sent: true } | 向房內其他成員廣播遊戲自訂訊息。 |
multiplayer.leave() | — | { left: true } | 離開目前房間並停止續租。 |
multiplayer.close() | — | { closed: true } | 關閉目前房間,僅房主可用。 |
ready() 回傳的能力
{
account: { signedIn },
locale,
region,
cloudSaves: { enabled, maxSlots: 10, maxBytes: 65536 },
multiplayer: {
enabled, maxPlayers, modes, roomPolicy,
managedUnlimited, canManageRooms, voice: false
}
}const platform = await OpenGames.ready();
const locale = platform.locale; // "zh-Hant", "en", "ja"…
const region = platform.region; // "TW", "JP", "US" or "XX"
loadTranslations(locale);
showRegionalNotice(region);ACCOUNT SAVES
每次寫入都要帶版本
玩家必須登入,創作者也要先在控制台啟用帳號存檔。資料必須可轉為 JSON。保存每次回傳的 version,下一次寫入時再送回;version 0 用於建立新槽位。
const loaded = await OpenGames.saves.load("campaign");
let version = loaded.save?.version ?? 0;
let state = loaded.save?.data ?? { level: 1, coins: 0 };
try {
const written = await OpenGames.saves.write(state, {
slot: "campaign",
version
});
version = written.save.version;
} catch (error) {
if (error.message === "VERSION_CONFLICT") {
// Reload and let the player choose which progress to keep.
}
}REALTIME MULTIPLAYER
房間負責傳送,遊戲定義規則
玩家必須登入。創作者要先在控制台啟用多人連線,設定允許模式、人數上限與房間政策。create、join 或 joinGlobal 成功後,SDK 會自動連到私人 Realtime 頻道。
shared所有玩家共享同一份狀態。
co-op玩家合作完成共同目標。
versus玩家競賽;計分與權威狀態由遊戲決定。
teams2–4 隊;成員分配由遊戲決定。
// Public co-op room
const created = await OpenGames.multiplayer.create({
visibility: "public",
mode: "co-op"
});
showInviteCode(created.room.room_code);
// Password-protected team room
await OpenGames.multiplayer.create({
visibility: "password",
password: playerEnteredPassword,
mode: "teams",
teamCount: 2
});
const { rooms } = await OpenGames.multiplayer.list();
await OpenGames.multiplayer.join(inviteCode, passwordOrNull);const stopMessages = OpenGames.on("multiplayer.message", ({ payload }) => {
applyRemoteMessage(payload);
});
const stopPresence = OpenGames.on("multiplayer.presence", ({ playerCount }) => {
updateLobbyCount(playerCount);
});
await OpenGames.multiplayer.send({
type: "input",
frame: 1024,
buttons: ["jump"]
});
// Call the returned functions when your game no longer needs the listeners.
stopMessages();
stopPresence();// Only the verified creator can create a persistent creator room.
await OpenGames.multiplayer.create({
creatorManaged: true,
persistent: true,
visibility: "public",
mode: "shared"
});
// Available only when the dashboard policy is "One game-wide world".
await OpenGames.multiplayer.joinGlobal("shared");房間限制
- 密碼房需要 4–32 字元;平台只保存不可逆雜湊。
- 控制台的玩家上限為 2–8 人;分組模式需要 2–4 隊。
- 同一帳號在單一建房流程最多保留 5 個開啟房間;公開清單最多回傳 50 房。
- 臨時房無活動 10 分鐘後關閉;SDK 會自動續租在線成員。
訊息限制
- 訊息必須可轉為 JSON,序列化後最多 8 KiB。
- 每個遊戲頁每秒最多傳送 30 次。
- 訊息不會回送給發送者;需要時請立即更新本機狀態。
- 不提供語音、持久聊天紀錄或權威遊戲伺服器。
隔離憑證、驗證房間成員,並處理邀請碼、私人頻道、Presence、密碼雜湊與傳輸限制。
實作大廳、訊息格式、權威規則、分隊、操作驗證、狀態重同步、重連與離線備援。
ERROR CONTRACT
處理穩定的橋接錯誤
SDK Promise 失敗時會拋出 Error。只有下列代碼可作為穩定分支依據。供應商、資料庫、瀏覽器與網路文字可能變動;未知訊息一律視為 REQUEST_FAILED,並提供重試或離線遊玩。
FEATURE_DISABLED創作者尚未啟用這項服務。
AUTH_REQUIRED玩家必須先登入 OpenGames 帳號。
VERSION_CONFLICT存檔已在別處更新;重新載入並讓玩家選擇保留版本。
MODE_NOT_ALLOWED控制台未啟用所選多人模式。
PLAYER_ROOMS_DISABLED房間政策不允許玩家自行開房。
CREATOR_ROOM_NOT_ALLOWED呼叫者不是已驗證創作者,或政策不允許創作者房。
GLOBAL_WORLD_DISABLED遊戲未設定全遊戲共用世界。
NOT_IN_ROOM傳送或關房前必須先建立或加入房間。
MESSAGE_TOO_LARGE序列化後的訊息超過 8 KiB。
RATE_LIMITED遊戲頁在一秒內傳送超過 30 則訊息。
HOST_ONLY只有房主可以關閉房間。
MULTIPLAYER_UNAVAILABLE目前環境無法使用 Realtime。
SEND_FAILED / ROOM_REQUEST_FAILED供應商或連線拒絕操作;請顯示重試或離線介面。
RELEASE CHECKLIST
檢查完整玩家流程
- 用 HTTP 伺服器開啟匯出資料夾,不要只用 file:// 測試。
- 測試鍵盤、滑鼠、觸控、手把、音效、全螢幕、所有場景與手機視窗。
- 修正所有 Console 錯誤、Network 缺檔、MIME 問題與大小寫不符。
- 測試未登入、已登入、存檔衝突、重連、房滿、密碼錯誤、房主離開與離線備援。
- 確認 ZIP 與多人訊息都不含密鑰、權杖、私人網址、個資或開發用檔案。
- 執行本機轉換檢查,從輸出內容重新建立 ZIP,上傳後再實際玩一次正式版本。