一场写死赛事的生命周期
设想开放世界里有一场手写的“港口滑板挑战”:固定地点、固定对手、固定路线,每周六中午开放。第一次参加时,玩家要摸索路线、观察对手,挺有意思;第三次,他已经知道哪个扶手可以抄近路、哪个NPC会在第二个台阶摔倒;第十次,这场比赛变成了领奖励的例行公事。最后玩家不再去了,港口的那片场地从此只剩装饰作用。
写死赛事的问题不在于质量差,而在于它和世界无关。下雨了它照办,那个NPC对手已经受伤了它照样出场,玩家已经是城市冠军了它还按新手难度来。赛事越多,世界反而越像一张时间表。在im体育里,我们希望体育赛事像真实的城市那样,根据当下条件持续发生。
约束表:动态不等于随机
把赛事改成动态生成,最常见的误解是“随机抽一个项目、随机选一个地点”。这样得到的会是暴雪天的户外篮球赛和平地上的速降赛。动态赛事必须同时满足一组约束:
| 约束 | 要检查什么 | 不满足时的结果 |
|---|---|---|
| Sport 项目 | 项目在这个区域是否有参与人群 | 不生成 |
| Location 地点 | 有没有对应设施:球场、坡度、破浪点、Spot | 换地点或不生成 |
| Time 时间 | 时段、季节、照明、潮汐窗口 | 调整开赛时间 |
| Weather 天气 | 降水、风、气温、能见度及趋势 | 延期、改室内或取消 |
| Player Level 玩家水平 | 玩家在该项目的技术等级 | 调整赛制与对手阵容 |
| NPC | 附近有谁、是否有空、状态如何 | 人数不足则缩小规模 |
| World State 世界状态 | 近期赛事、排名、俱乐部关系、地点事件 | 调整权重,避免重复 |
这张表里的每一行都可能否决一场赛事。生成器的大部分工作其实是排除,剩下来的才是合理的候选。完整的生成流程,从读取世界状态到邀请NPC再到结果写回,可以参考AI组织比赛那篇文章。
手写骨架,生成血肉
完全放弃手写也不对。设计师对一项运动的理解、对节奏的把握,是生成器替代不了的。我们的做法是分层:
- 手写的骨架:赛制模板(计时赛、淘汰赛、积分赛、对抗赛)、每个项目的规则部件、地点的设施标签、赛事之间的兼容规则。另外还有少量手写的标志性赛事,比如一年一度的雪山公开赛,它们是世界的固定锚点。
- 生成的血肉:具体在哪天、哪个地点、什么规则组合、哪些NPC参加、难度多少、奖励是什么。
在比例上,我们目前倾向于让手写标志赛事只占少数,作为季节和剧情的节点,大部分日常赛事由生成器在骨架内组合。这不是一个精确指标,而是设计方向:玩家应该能记住几场标志性比赛,同时每天出门都有可能碰到一场之前没见过的。
以一个模拟例子来说:周六中午港口仍然会有一场滑板赛,但今天因为上午下过雨,广场地面湿滑,生成器把比赛改到了有顶棚的停车楼;报名的NPC里有一位上周刚在城市排名上超过玩家的选手;赛制也从计时赛换成了连招积分赛,因为停车楼的坡道更适合连续动作。
我们在原型里踩过的坑
动态赛事也会失败,下面是几种典型的失败案例:
- 规则合法但不好玩:生成器拼出了一场“十公里山地车计时赛,终点在海拔更高处”,技术上成立,但全程爬坡非常枯燥。后来我们给每类赛制加入了节奏检查,比如速降类赛事必须以下坡为主。
- 玩家看不懂为什么:比赛突然改地点,玩家以为是漏洞。现在每次调整都会附带一句原因说明,例如“广场地面湿滑,改至停车楼”。
- NPC来源不合理:一场小镇社区赛出现了全区排名第一的选手。NPC的报名必须符合他的日程与目标,顶尖选手不会随便参加低级别比赛。
- 奖励失衡:某类赛事因为容易生成而奖励过多,玩家只刷这一种。奖励需要跟着难度与稀有度走。
频率控制:赛事不能淹没世界
生成器能力越强,越容易生成过多赛事。如果玩家每走一百米就弹出一个比赛邀请,世界就变成了另一种菜单。我们在频率上设了几道闸:
- 同一地点同一项目有冷却期,避免一个好场地被反复使用。
- 玩家周围同一时间可见的公开赛事数量有上限,其余的进入公告栏或赛事列表。
- 玩家连续拒绝某类赛事,就降低它的推送优先级,但不会停止生成,因为NPC之间照样会比。
- 恶劣天气时减少户外赛事,而不是用室内赛事全部补上,让世界有安静的一天。
最后一条值得强调:NPC之间的比赛会在玩家不参加时照常进行,结果照样写入排名。玩家可以在在App里查看AI赛事的页面上看到这些比赛的记录和即将开始的赛事。对im体育AI来说,赛事的意义不在于给玩家发任务,而在于让世界里始终有人在比赛,玩家随时可以加入,也可以只是路过。这也是im体育开放世界不把赛事全部写死的原因。