Steam 创意工坊完整实现指南

Steam 创意工坊完整接入指南:从内容格式到上线维护

游戏接入 Steam 创意工坊,需要同时设计创作工具、Steamworks 配置和游戏内的内容加载流程。本指南面向游戏开发者与 Mod 工具开发者,按从准备文件格式、实现上传与订阅,到测试上线和管理版本的顺序介绍完整工作。

创作者提交内容,经 Steam 工坊分发并由游戏加载的流程

先确定作品如何进入游戏

决定允许创作者修改什么:地图、配置、外观或其他资源分别需要怎样的文件、版本标识和校验规则。游戏应能从一个工作目录加载尚未上传的内容,让作者先测试;发布工具负责检查目录、必需文件、预览图及游戏能否识别这些资源。Steam 负责托管、展示和传输,游戏仍需实现文件解析、依赖处理与安全加载。

即用型适合让玩家直接订阅可用内容,作者可更新作品,开发者应提前提供编辑工具和校验机制。鉴选型让社区提交内容供开发者评估,再由开发者决定如何集成;例如开发者可以将资源整理进游戏 depot,或对已接纳的内容采用直接下载方案。若设计有限拥有或销售,还需考虑库存、授权及支付规则。先根据内容控制程度和维护能力选择模式,再设计上传界面。

单人和多人场景要分别测试:多人游戏若需要参与者使用相同地图或模组,应让客户端在加入前识别所需项目、下载并验证版本。工坊显示的软依赖不能代替游戏自己的加载规则。

在 Steamworks 配置工坊与云配额

用拥有管理权限的账号打开游戏的 Steamworks 应用管理页面,进入“编辑 Steamworks 设置”。建议按以下顺序配置并发布:

  1. 在 Steam 云设置中,设置每用户字节配额和文件数量配额,保存。工坊预览图使用这些配额。
  2. 在“创意工坊”配置的“附加配置选项”中启用“为文件传输启用 ISteamUGC”,保存。
  3. 在“创意工坊 → 通用”选择曝光状态:仅开发者、开发者和测试人员、顾客和开发者,或所有人。测试阶段先限制访问。
  4. 在“发布”选项卡选择准备发布并发布到 Steam。修改配置后需要完成发布流程,保存本身不等于生效。

工坊默认不向公众开放。将曝光状态设为所有人之前,应完成工坊清单,包括形象素材、标题、描述和至少一个公开项目。上传工具若使用独立 App ID,需在游戏的工坊配置“应用发布权限”中添加工具 App ID,并为游戏和工具两个应用配置云配额及发布设置。创建项目时的消费 App ID 仍应传游戏 ID。

建立上传和更新流程

客户端完成 Steamworks 初始化后,通过 SteamUGC() 使用接口,并持续运行回调。创建、更新和安装涉及不同的异步结果,不应在拿到请求句柄时就显示“上传成功”。

  1. 作者准备一个内容文件夹和主预览图,工具先校验格式和路径。调用 CreateItem,传游戏 App ID 和适用的文件类型;可订阅内容通常使用 k_EWorkshopFileTypeCommunity,鉴选提交使用 k_EWorkshopFileTypeMicrotransaction。
  2. 等待 CreateItemResult_t,检查 m_eResult;成功后保存 m_nPublishedFileId,以后更新同一项目时继续使用它。检查协议标志,按提示引导作者处理。
  3. 用游戏 App ID 和项目 ID 调用 StartItemUpdate,再按需要设置标题、描述、语言、可见性、标签、内容目录和预览图片。逐项检查设置函数的返回值。
  4. 调用 SubmitItemUpdate,等待 SubmitItemUpdateResult_t 并检查结果与协议标志。提交后不能取消本次上传;GetItemUpdateProgress 可提供处理阶段和字节数,总数可能随阶段变化。

SetItemContent 指向目录,现代工坊项目可以包含多个文件。为高效传输,官方建议不要把全部内容合并压缩成单个文件。需要在下载前向浏览器提供自定义信息时,可设置元数据,查询时显式请求该字段。

协议与项目页面

创作者尚未接受创意工坊协议时,项目默认隐藏。上传界面应在提交按钮附近提供协议说明和入口;创建及更新结果都可能提示用户需要处理协议。提交后可使用 ISteamFriends::ActivateGameOverlayToWebPage 打开 steam://url/CommunityFilePage/<项目ID>,让作者核对页面并自行处理需要的协议或设置。游戏不应替用户接受协议。

ShowWorkshopEULA 可显示协议,返回 false 表示叠加界面无法显示;GetWorkshopEULAStatus 可查询状态。曾接受旧版本也可能使 m_bAccepted 为真,判断是否需要新操作时还要检查 m_bNeedsAction。

从订阅到内容可用

用户可以在工坊页面订阅,也可以通过游戏内的 SubscribeItem 和 UnsubscribeItem 管理订阅。用 GetNumSubscribedItems 和 GetSubscribedItems 枚举列表;当前接口默认排除本地禁用项,按需要设置包含选项。服务器调用这两个函数返回 0。

游戏启动后,新订阅的项目仍可能在后台下载。对每个 ID 用 GetItemState 检查可组合的状态标志;已安装也可能同时需要更新。注册 ItemInstalled_t 以及外部订阅和取消订阅事件,并检查事件的 App ID,避免处理属于其他应用的通知。

需要主动下载时调用 DownloadItem。返回 true 只说明下载已开始;等待 DownloadItemResult_t,核对 App ID、项目 ID 和结果后,再调用 GetItemInstallInfo 获取本地路径并校验文件。高优先级会暂停其他正在进行的 Steam 下载,应有明确场景再使用。未订阅项目可能只在临时缓存中;取消订阅的文件通常在游戏退出后移除。下载进度可通过 GetItemDownloadInfo 读取,总字节数在下载开始后才有效。

实现浏览与查询

按用途选择查询:用户列表使用 CreateQueryUserUGCRequest,全局浏览使用 CreateQueryAllUGCRequest,已知 ID 的详情使用 CreateQueryUGCDetailsRequest。创建句柄后,在发送前设置搜索、标签和所需返回字段,再调用 SendQueryUGCRequest。

收到 SteamUGCQueryCompleted_t 后,检查结果并按实际返回数量读取项目;需要子项目、键值标签、元数据或额外预览时,提前启用对应 SetReturn... 选项。结束时调用 ReleaseQueryUGCRequest,失败路径也要清理句柄。用户和全局列表分页从 1 开始,每页最多 50 条;具体查询类型支持的过滤条件不同,需检查设置函数返回值。

专用服务器和临时下载

专用服务器可从运营者配置或客户端取得项目 ID,再通过服务器的 Steamworks 接口请求下载,等待结果后定位内容。服务器应自行验证 ID、内容格式、依赖与版本,客户端提供的 ID 不代表文件适合直接执行或加载。未订阅的下载可能只是临时缓存。

多个服务器共用安装目录时,可在任何 UGC 命令前调用 BInitWorkshopForGameServer,提供服务器 depot ID 和工坊目录绝对路径。服务器应使用 SteamGameServerUGC() 和 SteamGameServer_RunCallbacks(),并配置专用服务器所需的可再发行文件。

用 SteamCMD 验证上传配置

SteamCMD 的 workshop_build_item 适合开发测试;它需要 Steam 登录,因此不应要求普通创作者向你的工具提供账号凭据。下面是原创示例,路径、App ID 和文字均需替换为自己的测试数据,文件中不应保存凭据:

"workshopitem"
{
    "appid"          "123456"
    "publishedfileid" "0"
    "contentfolder"  "D:\\WorkshopTest\\Content"
    "previewfile"    "D:\\WorkshopTest\\preview.png"
    "visibility"     "2"
    "title"          "测试地图"
    "description"    "用于验证上传流程的测试项目"
    "changenote"     "首次测试"
}

在已登录的 SteamCMD 交互会话中执行 workshop_build_item <VDF文件路径>。创建项目时必须有 appid,并将 publishedfileid 省略或设为 0;更新项目时两个值都要提供。官方说明更新某个键时,其余键值也应保留在 VDF 中。成功后文件中的 publishedfileid 会写入新 ID,再使用同一文件将更新该项目;应检查目标 ID,避免误更新。

标签设计和发现

默认情况下,通过 SetItemTags 提交的标签会出现在工坊首页供筛选。在 Steamworks 的“创意工坊 → 标签”中,可以指定展示的标签、分类标题以及仅管理员可见的标签。配置名称必须与上传的标签完全一致,否则不能按预期筛选。

上传过带某标签的项目后,该标签不能从工坊中删除;可以通过配置覆盖显示列表,隐藏不想向浏览者展示的标签。因此上线前应先建立稳定的标签表,并让上传器从受控选项中选择。机器可读的键值标签可用于精确查询,不能代替面向玩家的清晰分类。

让项目匹配游戏分支

默认情况下,订阅者获得项目最新版本。Steamworks SDK 1.60 起支持为项目版本指定适用的游戏测试分支范围。要启用这一机制,先到 Steamworks 的“SteamPipe → 生成版本”按从旧到新的顺序整理分支,再在工坊配置中启用游戏分支版本并发布设置。分支顺序决定最小值与最大值的范围,后续维护应保持有序。

作者可在项目历史页面设置支持范围;上传工具也可在提交内容时调用 SetRequiredGameVersions。最小和最大分支相同表示仅匹配该分支;留空一端表示向该方向延伸,两端均未指定表示适用于所有游戏构建。该设置只在实际内容发生变化时应用。多个项目版本同时匹配当前分支时,Steam 下载其中最近上传的版本。

游戏可以查询 GetNumSupportedGameVersions 与 GetSupportedGameVersionData,并结合 ISteamApps 的分支信息提示可能不兼容的作品。若允许玩家调用 SetActiveBeta 切换,应先说明游戏会退出、安装目标分支并重新启动,让玩家有机会保存进度。公开大版本前先提供测试分支,给作者验证和更新作品的时间。

封闭测试、上线和排错

先用 Steam 测试分支交付带工坊功能的游戏版本;需要限制工坊访问时建立 Steam 社区组,在组资料中取得组 ID,将工坊曝光状态设为“开发者和测试人员”,填入组 ID 并发布设置。仅通过家庭共享或免费周末等临时许可访问应用的账号不能上传,因此测试账号应具备符合要求的许可。

测试应覆盖作者创建、协议处理、上传、另一个账号订阅、等待下载、游戏加载、作者更新、客户端重新加载和取消订阅。额外验证缺失文件、下载失败、模组不兼容、多人内容一致性,以及独立上传工具的发布权限和两个应用的云配额。上线素材包括工坊形象图、标题、简短介绍和工具文档;公开前确认至少一个适合展示的项目已公开。

排查时保留项目 ID、应用 ID、步骤和 EResult:下载或安装查看 Steam/logs/Workshop_log.txt;上传和更新查看 Steam/workshopbuilds/depot_build_<appid>.log。CreateItemResult_t、SubmitItemUpdateResult_t 和 SteamUGCQueryCompleted_t 都包含结果字段。收集日志前应让用户检查其中的环境信息。SDK 的 SpaceWar 示例可以辅助理解订阅枚举、安装检查和安装事件,但游戏仍需实现自己的内容验证。

资料来源:创意工坊概览、实现指南、标签、项目版本控制。