Phaser UGC 关卡编辑器:保存、校验、分享码和安全边界

讨论 Phaser 玩家自定义关卡编辑器中的格子编辑、撤销重做、保存格式、可玩性校验、分享码和内容安全。

UGC 编辑器不是把开发工具开放给玩家

让玩家自定义关卡很有吸引力。Phaser 做 2D 编辑器也不难:格子地图、素材面板、拖拽放置、保存分享。但 UGC 一旦上线,就不只是工具问题,还涉及可玩性、作弊、内容安全、兼容、分享和审核。把内部关卡编辑能力直接开放给玩家,通常会出事。

我做过一个解谜 H5 的玩家关卡编辑器。第一版允许玩家放墙、机关、钥匙、出口,然后生成分享码。很快出现几个问题:玩家做出无解关卡,分享码太长无法复制,旧版本打不开新机关,某些玩家用分享码塞入异常数据导致页面卡死。编辑器本身能用,但没有安全边界。

UGC 编辑器要把“编辑体验”和“运行安全”分开。玩家可以自由创作,但提交和游玩前必须经过格式校验、可玩性校验、资源白名单和版本检查。Phaser 负责编辑交互和预览,关卡数据必须是受控结构。

flowchart TD
    A[玩家编辑关卡] --> B[本地 LevelDraft]
    B --> C[撤销/重做和实时预览]
    B --> D[格式校验]
    D --> E[可玩性校验]
    E --> F{是否通过}
    F -->|否| G[提示修复位置]
    F -->|是| H[压缩并生成分享码/上传]
    H --> I[其他玩家加载前再次校验]

数据格式要白名单化

玩家关卡数据不应该允许任意对象。每个 tile、机关、怪物、装饰都来自白名单。数据里保存 id、坐标、朝向、参数,不保存脚本或任意代码。客户端加载分享码时,只按白名单解释。

格式要有版本。比如 levelVersion=3,包含 width、height、tiles、objects、metadata。旧客户端看到更高版本,可以提示需要更新,而不是尝试解析未知字段。新客户端读取旧版本时,可以迁移或补默认值。

数据体积也要限制。地图宽高、对象数量、文本长度、机关数量、嵌套结构都要有上限。不要让一个超大分享码让浏览器解压半天。所有外部输入都要当成不可信数据。

编辑操作要支持撤销重做

编辑器没有撤销,玩家会很谨慎,不敢尝试。撤销重做可以用 command 模式:放置 tile、删除对象、移动对象、修改属性都是一个 command,包含 do 和 undo。不要每次操作都复制整张大地图,体积会很大。

但也不要过早优化。小地图可以先保存快照,确认体验后再改 command。关键是状态变化必须集中,不能某个按钮直接改 tiles,另一个按钮直接改 objects。否则撤销栈无法覆盖所有操作。

拖拽连续绘制墙体时,可以合并成一个 command。玩家按住拖过 30 个格子,撤销一次应该撤掉整条墙,而不是撤一格。编辑体验的细节会直接影响玩家是否愿意创作。

可玩性校验要给具体原因

UGC 最大问题是无解关卡。至少要校验出生点唯一、出口存在、出生点到出口可达、关键钥匙可达、必需机关数量正确、敌人不堵死出生点。更复杂的解谜可能需要模拟规则,判断是否存在通关路径。

校验失败时,要告诉玩家哪里错了。比如“出口不可达”“钥匙 A 被墙封住”“出生点周围没有可移动格”。最好在编辑器里高亮问题位置。只弹“关卡无效”,玩家不知道怎么修。

可玩性校验可以分等级。基础校验必须通过才能分享,高级校验给警告:路径太短、敌人过多、奖励不可达、难度异常。不要因为一个非致命警告阻止创作,但要让玩家知道问题。

分享码要可压缩也可诊断

分享码适合轻量 H5 游戏,但要设计格式。可以把 JSON 经过精简、压缩、base64url 编码。分享码里包含版本、地图数据和校验摘要。加载时先解码,再校验版本和结构。

不要把玩家昵称、账号 token 或敏感信息塞进分享码。分享码会被复制到聊天、社交平台和论坛。它应该只包含关卡内容和必要元数据。若需要作者信息,用服务器 id 或公开昵称,并经过审核。

分享码太长会影响传播。可以限制地图规模,或者上传服务器后生成短码。短码模式下,客户端仍要校验服务器返回的数据。服务器存储不能替代客户端安全校验。

内容安全和审核

UGC 不只是技术风险,还有内容风险。玩家可能用方块拼出不合适图案,用关卡名写广告或辱骂,用分享码传播恶意内容。即使是纯格子游戏,也要考虑审核策略。

最简单的做法是限制文本输入,关卡名长度和字符集受控,敏感词过滤。图案类内容可以先做举报机制和人工审核。公开推荐列表必须审核后展示,私下分享可以低门槛但保留举报入口。

客户端不要执行玩家提供的脚本。机关逻辑通过内置组件组合,例如按钮、门、传送、计时器。玩家配置参数,但不能写代码。这样既安全,也更容易做可玩性校验。

编辑器和游玩模式要共用解析器

编辑器里能预览通过,不代表正式游玩能通过,如果两套解析逻辑不同。LevelParser 应该同时服务编辑器预览和游戏运行。编辑器保存的是 LevelData,正式关卡加载也是 LevelData。这样玩家看到的和分享出去的更一致。

预览模式要接近真实玩法,但可以保留退出和重置按钮。玩家测试自己关卡时,记录是否成功通关。某些游戏可以要求创作者自己通关一次才能分享。这是很有效的质量门槛。

编辑器 UI 和玩法 UI 要分层。放置工具、属性面板、网格高亮属于编辑器层;角色、机关和敌人属于预览玩法层。切换模式时清理输入状态,避免编辑操作影响试玩。

一个 LevelData 形状

下面示例展示受控数据结构。它只包含白名单 id 和参数,不包含任意函数。

type LevelData = {
  version: number;
  size: { w: number; h: number };
  tiles: Array<{ x: number; y: number; tileId: string }>;
  objects: Array<{ id: string; type: string; x: number; y: number; props?: Record<string, string | number | boolean> }>;
};

function validateLevel(data: LevelData, registry: ObjectRegistry): ValidationResult {
  if (data.size.w > 64 || data.size.h > 64) return { ok: false, reason: 'map-too-large' };
  return validateObjects(data.objects, registry);
}

这个结构可压缩、可校验、可迁移。对象 props 也要按 type 校验,不能任意塞字段。比如 door 允许 color,enemy 允许 enemyId,textSign 允许 textKey 或短文本。

调试和运营工具

UGC 上线后,运营需要看到热门关卡、失败率、通关率、举报数、平均游玩时长。客户端可以上报关卡 id、版本、开始、成功、失败原因。不要只看分享次数,很多被分享的关卡可能不可玩。

开发版需要关卡导入导出、校验详情、性能统计。玩家分享一个有问题的码,工程能粘贴进去复现。解析失败也要显示具体错误:版本不支持、字段缺失、对象超限、校验不通过。

如果支持服务器短码,后台要能下架关卡。客户端加载被下架关卡时显示原因,而不是 404 空白。内容安全闭环必须包含下架和举报。

上线前检查清单

上线前检查:数据格式是否白名单,版本是否存在,地图尺寸是否有限制,撤销重做是否覆盖所有操作,可玩性校验是否具体,分享码是否可解码诊断,编辑器预览是否共用解析器,公开列表是否有审核或举报。

还要测试异常分享码、超大地图、旧版本数据、新机关旧客户端、文本敏感词、玩家未通关就分享、服务器短码失效、页面刷新恢复草稿。UGC 的失败输入来自真实玩家,不能只测自己做的标准关卡。

草稿保存和发布状态要分开

玩家编辑关卡可能花很久。浏览器刷新、页面后台、手机来电都会打断编辑。如果没有草稿保存,创作者会非常沮丧。草稿可以本地保存,包含未发布关卡、撤销栈摘要和编辑器版本。再次进入编辑器时提示恢复草稿。

草稿和已发布关卡要分开。草稿可以包含临时无效状态,比如出口还没放;发布版本必须通过校验。玩家继续编辑已发布关卡时,应该生成新版本草稿,发布后形成新的 levelVersion。旧分享码是否指向旧版本还是新版本,要有产品规则。

如果支持更新已发布关卡,还要处理玩家正在游玩旧版本的情况。最好让每个分享码绑定一个不可变版本,新版本生成新码或在服务器记录版本链。否则玩家 A 分享的关卡,玩家 B 玩到一半时作者修改了地图,会造成结果不一致。

评分和推荐要防刷

UGC 一旦有公开列表,就会有排序问题。最热、最新、精选、好友分享、通关率高,都可以作为入口。但点赞、评分和通关数据可能被刷。客户端不能自己决定推荐结果,只能展示服务端筛选后的列表。

客户端仍然要提供真实体验数据:开始游玩、通关、失败、退出、举报、收藏。服务端根据这些数据做推荐。不要只看点赞数,很多低质量关卡也可能靠标题吸引点击。通关率、平均时长和举报率更能反映质量。

推荐列表还要有安全兜底。被举报或下架的关卡应立即从列表隐藏,已收藏玩家再次打开时给出说明。客户端加载列表时要能处理关卡缺失、版本不支持和网络失败,不要因为某个关卡数据坏了导致整个列表空白。

编辑器性能也要预算

编辑器里玩家可能连续涂墙、拖动大型选择框、复制粘贴区域。每次操作都全量重绘地图,会在低端设备上卡。可以把编辑层分成静态 tile 层、对象层、选择层和预览层。涂 tile 时只更新变化区域,选择框用 Graphics 单独画。

撤销栈也要有上限。保存太多快照会占内存,尤其在移动浏览器里。可以限制最近 100 步,或者按操作体积限制。超出时提示无法继续撤销,而不是让页面被内存压垮。

教程和模板决定创作门槛

UGC 编辑器功能再完整,如果玩家不知道怎么做出好关卡,也很难形成内容生态。内置模板很重要:空白地图、基础跳跃、钥匙开门、机关谜题、战斗房间。玩家从模板改,比从零开始更容易。

教程也要可操作。第一次进入编辑器,不要只弹说明文字。可以引导玩家放置出生点、出口、墙、钥匙,然后点击测试。每一步都检查玩家是否完成。教程本身也要能跳过,熟练玩家不应被强制教学打断。

模板还可以作为校验参考。每种模板有推荐尺寸、对象数量和难度范围。玩家超出太多时,编辑器给出提示:敌人过多、路径过长、奖励太少。这些提示不是限制创造,而是帮助玩家做出更容易被别人玩的关卡。

分享链路要减少流失

玩家完成关卡后,分享流程要短。保存、校验、生成码、复制、打开好友分享,任何一步失败都会降低传播。分享码生成后要立即可测试,最好提供“复制并试玩链接”。接收者打开链接后,先显示关卡标题、作者、难度和版本,再进入加载。

分享失败也要可解释。网络失败、关卡未通过校验、内容被拦截、版本不支持,都要给出具体原因。不要只显示“分享失败”。UGC 的增长依赖玩家愿意传播,传播链路必须比普通设置页更可靠。

如果支持二维码或短链,客户端仍要能处理过期和下架。打开失效链接时,显示“关卡已下架”或“版本过旧”,并推荐其他关卡。不要让玩家落到空白页。

分享成功后也可以引导作者试玩一次公开链接,确认别人看到的版本和自己编辑器里的版本一致。

结语

Phaser 很适合做轻量 UGC 关卡编辑器,但开放创作不等于放弃边界。数据格式、白名单、校验、分享码、审核和回放都要先设计。否则玩家创造力越强,系统越容易被意外输入冲垮。

好的 UGC 系统让玩家自由表达,也让游戏能安全运行。编辑器要好用,分享要方便,加载要可信,问题要能诊断。做到这些,UGC 才会从一次活动玩法变成长期内容来源。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页