下载 App

《我真没让他们建城啊!》开发者日志 02

修改于10/168 浏览
先让人看懂,再让数据说话 一个涌现游戏最大的敌人,不是"世界不够复杂",而是"玩家不知道这一切跟自己有什么关系"。 第二大的敌人是:你以为你测出来的数,是真的。
日期: 2026-10-09 当前进度: 新手引导 + 数值调参层完成;数值体检发现战争链路与可复现性问题
写在前面:从"能跑"到"能被看懂" 上一篇日志(01)讲的是怎么让世界长出来——七张热度场、Utility AI、20 项文明现象图鉴。
今天要解决两个新问题:
世界长出来了,但新玩家不知道自己在看什么。 屏幕上是一群小豆子在乱走,没有任务栏、没有血条、没有"点击建造"。玩家大概率乱点两下就退了。 数值调完了,但我不知道自己调得对不对。 手感是主观的,需要一套能跑的数据来告诉我"这一局到底发生了什么"。 所以今天的三件事是一条线:
新手引导——第一次进来该看到什么、什么时候看到(Tutorial.lua) 数值统一——把所有调参入口收进一个文件(GameBalanceConfig.lua) 无头体检——跑 900 秒 × 3 个种子,用数据验收(scripts/_proc/) 结果是:第 1、2 件做完了,第 3 件顺藤摸出了两个真问题。
一、新手引导:只在玩家第一次需要时教 设计文档 §63 里写死了一条红线:
新手引导绝对不能开场连续弹 8 个框。
错误示范:
text
复制 欢迎来到游戏 → 这是人口 → 这是资源 → 这是神之手 → 这是性格 → 这是道路 → 这是市场 → 这是规则卡 → 这是文明图鉴 玩家看完的唯一感受是:这个游戏系统好多。然后关掉。
正确的做法只有一句:
只在玩家第一次需要某个东西时,才教它。
1.1 节奏:五拍,每拍只教一件事 Tutorial.lua 只维护状态,不画任何东西——所有画面由 Render 读它的字段完成。教学逻辑和渲染彻底解耦,改节奏不用碰渲染代码。
阶段 触发 做什么 intro 开局 两句话,约 4.8 秒,不弹完整教学 place intro 结束 常驻提示"试着在左侧「资源」里放一些食物",同时地图高亮食物落点 quiet 玩家真的投下食物 20~40 秒不弹任何教学 road 第一条道路形成 6 秒全屏过场,整个新手流程的高潮 free 过场结束 自由观察,一次性提示按需触发 两个刻意的设计:
第二拍的提示是"常驻"的(hintSticky = true)。它不会被计时器清掉,只有玩家真的投下食物才消失。因为玩家读完提示还要摸索怎么拖拽——如果提示读得慢就消失了,教学就白做了。
第三拍是刻意的留白。20~40 秒什么都不教,让玩家盯着小豆人看。这段时间里小豆人会开始吃东西、走动、踩出第一道痕迹——是游戏在教玩家,不是我在教玩家。
1.2 把"第一条道路"做成高潮 整个新手流程唯一一个"大场面"给了第一条道路(§68)。
因为道路是这个游戏第一个"WOW 时刻"——玩家第一次亲眼看到自己什么都没做,世界却变了。这一刻必须在教学里被放大,不能一闪而过。
顺序很重要:先让玩家看到现象,再告诉他"你可以做更多"。 反过来就变成说明书了。
1.3 HUD 渐进开放 设计文档 §73 要求首局隐藏复杂功能,所以工具栏和图鉴是逐步解锁的:
功能 解锁条件 资源(食物/木材/石头) 始终开放 文明图鉴 第一条道路形成后 世界规则 玩家选过第一张规则卡后 危险(狼群/野火) 第一次遇到狼,或 300 秒后 诱因(篝火/宝藏/图腾/钟) 240 秒后 玩家开局看到的工具栏是短的。随着他理解世界,工具栏才一点点变长。
1.4 一个容易忽略的细节:教学不能污染模拟 写 Tutorial.Reset() 时卡了一下:安静观察期的时长要有点随机性(20~40 秒),不然每局都一样。但不能用 math.random。
因为模拟是固定步长、确定性伪随机的——资源分布、小豆人性格全部由地图种子推导。如果引导在这里消耗一次随机数,"玩家是否触发过教学"就会改变世界演化,同一颗种子在不同玩家手里会跑出不同结果。
所以安静时长从地图种子推导:
lua
复制 Tutorial.quietDuration = TC.QuietMin + math.floor(Config.Hash2(B.MapConfig.Seed, 97) * (TC.QuietMax - TC.QuietMin + 1)) 一条原则:教学是"观察者",不能污染模拟。 这和 01 里"涌现系统只能命名、不能创造"是同一条原则的延伸。
二、数值统一:把参数收进一个文件 项目现在约 7000 行 Lua,参数散落在 World、Agent、Emergence、Systems 各处。调一个繁殖概率要翻三个文件,改一个阈值不知道哪里还在引用。
于是建了 GameBalanceConfig.lua,按模块归类:
lua
复制 B.TimeConfig -- 固定步长、各阶段起始时间 B.MapConfig -- 地图尺寸、资源点、出生点、种子 B.AgentConfig -- 人口、寿命、性格、繁殖、感知 B.NeedConfig -- 饥饿、疲劳、恐惧、社交 B.ResourceConfig -- 资源容量、采集时长、再生 B.HeatMapConfig -- 七张热度场的衰减与阈值 B.SettlementConfig -- 聚落形成、升级、迁徙 B.TribeConfig -- 部落独立距离、关系、敌意阈值 B.CombatConfig -- 战斗、狼群、战争判定 B.RuleCardConfig -- 12 张规则卡 B.EventConfig -- 7 个随机事件 B.TutorialConfig -- 新手引导节奏 两个刻意的约定 约定一:单位写进文件头。
-- 时间:游戏秒;距离:Cell。Config.CELL 仅负责将逻辑距离换算为绘图坐标。 这个项目里有三种"长度":逻辑格子(Cell)、绘图像素、屏幕逻辑像素。混用一次就是一场 debug。把单位钉在文件顶部,比任何注释都管用。
约定二:阈值旁边写"为什么是这个数"。
lua
复制 -- IndependentDistance 必须 <= SettlementConfig.CoreGap(10),否则间距落在 -- 两者之间的新聚落会被永久并入第一个部落,第二部落永不诞生,战争无从发生。 IndependentDistance = 10, 这条注释是 01 里"部落分裂距离"坑的产物。数值文件里最值钱的不是数字,是数字旁边那句为什么。
三、无头体检:让数据说话 数值调参最怕两件事:凭感觉调、改了 A 不知道 B 崩了。
所以写了一组无头诊断脚本,放在 scripts/_proc/,用 .cli/UrhoXRuntime 直接跑,不开图形界面:
脚本 干什么 balance_audit.lua 3 个种子 × 900 秒,输出关键指标 + 首次现象时间对照设计目标 war_diag.lua 专测战争:战斗热度峰值 / 部落数量峰值 / 跨部落击杀 balance_diag.lua 死亡构成、交易时间分布、人口曲线 determinism.lua 单次运行,供跨进程对比确定性 leak_diag.lua 同进程连跑多局,用状态指纹定位跨局状态泄漏 3.1 三颗种子的体检报告 跑完 900 秒(一局完整时长):
指标 seed 21021 seed 777 seed 4242 均值 峰值人口 132 139 121 130.7 出生 / 死亡 215 / 113 226 / 126 212 / 115 217.7 / 118.0 道路长度 150 140 150 146.7 聚落数 1 2 2 1.7 城市数 0 2 0 0.7 交易次数 62 345 117 174.7 商路数 0 1 1 0.7 图鉴解锁 6 10 9 8.3 战争次数 0 0 0 0 三个种子都 standardPassed = true——但最后一行那个全 0 太扎眼了。
3.2 首次现象时间 vs 设计目标 体检脚本内置了一张对照表(设计文档 §一 的目标时间):
现象 设计目标(秒) seed 21021 实测 结论 首次采集 10~20 11.5 ✅ 首次道路 45~180 58.1 ✅ 首次交易 120~240 34.7 ⚠ 偏早 首次冲突 240~420 46.0 ⚠ 偏早 首次死亡 240~420 264.9 ✅ 新手引导最关键的那条——首次道路 58 秒——正好落在"3 分钟内看到明显涌现"的验收区间里。这是今天最想确认的数,它成立了。
但交易和冲突来得太早了:设计上希望玩家先安静观察一分钟,再看到交易和打架;实测 35 秒就交易、46 秒就打架。这会让 quiet 那段留白变得很吵——玩家还没来得及"看",世界就已经热闹起来了。
四、追一个"从不发生的战争" 三颗种子的 wars 全是 0。这不是"偶尔没打起来",是三局都没打起来。一个 GameJam 里最戏剧化的系统,等于不存在。
4.1 先画出战争的三层门槛 代码里战争是这样触发的(Emergence.lua):
text
复制 第一层:至少存在 2 个部落 └─ 聚落人口 ≥ IndependentPopulation(8) 且 与最近聚落距离 > IndependentDistance(10)
第二层:两个部落的关系 ≤ HostileThreshold(-20) └─ 关系从 +10 开始,抢劫 -5 / 攻击 -8 / 击杀 -15 只有"敌意"关系才会主动攻击
第三层:战场内战斗热度 ≥ WarHeat(150) 且 30 秒窗口内 同一对部落 的跨部落死亡 ≥ 3 └─ 满足才记一次"战争" 4.2 诊断数据(真实运行结果) war_diag.lua 每秒采样,跑完 900 秒 × 3 种子:
种子 战斗热度峰值(需 ≥150) 部落峰值 跨部落击杀 关系极值 战争 21021 154.3 1 0 0.0 0 777 387.0 2 0 +14.0 0 4242 453.0 2 35 +100.0 5 这张表比任何猜测都清楚——三颗种子卡在了三个不同的层:
21021 卡在第一层:部落峰值只有 1。战斗热度 154.3 刚过线,但只有一个部落,不存在"跨部落"这回事。第二聚落没能长成独立部落。 777 卡在第二层:部落有 2 个,战斗热度高达 387,但关系极值是 +14(正的!),跨部落击杀 0。两个部落过得太好了,从没结仇,所以从不互相攻击。 4242 反而打通了:2 个部落、关系推到 +100(说明有大量往来)、35 次跨部落击杀、5 场战争。 我原本以为是"地图太小,聚落长不到 10 格远"这一个原因。数据证明我错了——是三个不同的门槛各自在不同的局里失效。
顺带一提:三局里狼击杀全部为 0。狼群会生成、会过境(日志里能看到 生成狼 wolf1..wolf5),但没有杀死过任何小豆人。这又是另一个"写了的系统没真正生效"的信号。
4.3 一个更麻烦的发现:900 秒下同种子不可复现 排查到一半,我注意到一件更严重的事:
同一颗种子 4242,在 22:00 的体检里是 0 场战争,在 22:17 的单跑里是 5 场战争。
两次运行之间没有改过任何代码(最后一次构建是 21:23)。
于是先验证确定性。determinism.lua 跑 seed 777 × 400 秒,三个独立进程结果完全一致:
[det] seed=777 峰值=67 出生=62 死亡=17 道路=74 聚落=1 交易=54 ← 三次完全相同 400 秒尺度是确定的。但 900 秒尺度下,同代码、同种子给出了 0 和 5 两种结果。
这意味着:我上午那份体检报告本身是不可信的。 它可能只是恰好跑到了某个分支。基于它的所有调参结论(包括"首次交易偏早")都要打问号。
这比"战争没发生"严重得多——它意味着我的测量工具坏了。 在修好它之前,任何数值调整都是盲调。
目前定位到的方向(还没定论):
400 秒一致、900 秒不一致,说明分歧出现在长跑的后段,很可能是某个累积状态或迭代顺序在长时间后才放大成可见差异; leak_diag.lua 就是为这个写的:同进程连跑 [4242] 和 [777, 4242],逐秒记录状态指纹(人口 + 所有小豆人坐标/需求之和 + 部落数 + 道路长度),找第一个分歧秒,从而二分定位到具体模块。 这一步是明天的第一件事。
五、今天踩到的三个"看不见的耦合"
  1. 教学随机数会污染模拟。 新手引导看起来和玩法无关,但只要它用了一次 math.random,确定性就没了。观察者必须零副作用。
  2. 一个阈值"对不对",取决于地图尺度。 IndependentDistance = 10 单看合理,但地图只有 64×64、聚落间距普遍小于 10,这个数字就可能永远不满足。数值不能脱离尺度单独评审。
  3. 三层门槛,可能三层同时失效,而且失效原因各不相同。 战争不是"一个 bug",是三个独立的门:部落没分裂、关系没恶化、规模不够。修一个不等于通。
六、下一步 [ ] 最高优先级:修可复现性。 用 leak_diag.lua 找 900 秒分歧点,在测量工具可信之前不调任何数值 [ ] 修战争链路:三个门槛逐一验证——部落分裂(21021)、关系恶化(777)、规模(4242) [ ] 查"狼击杀 = 0":狼生成了却没造成任何死亡,同样是"写了没生效" [ ] 压前段节奏:把首次交易、首次冲突推回设计目标区间 [ ] 补 UI/UX 文档 §66/§72:明确"新手教学不教的内容"(AI 原理、性格、规则卡机制一律不教) [ ] 结算界面、宣传 GIF、投稿材料 写在最后 01 里我说,这个项目最爽的瞬间是"等等,他们为什么突然开始干这个了?"
今天补上了它的两个前提:
第一,玩家得先愿意留下来看。 新手引导不是"教玩法",是保护玩家第一次看到涌现时的那份好奇。少弹一个框、晚一秒解释、多留二十秒空白,都是在给那一刻让路。
第二,我得先能相信自己在看的东西。 一个测不准的系统,比一个没做好的系统更危险——因为你会拿着假数据,自信地往错误的方向调。
今天最有价值的产出,不是新功能,是那张三颗种子卡在三个门槛的表,和那句"同一颗种子跑出两个结果"。涌现游戏里,"没发生"和"发生了"一样重要,而"测不准"最要命。
#聚光灯gamejam开发者日志
开发者日志04|有人在看着你,也有人在议论你截图
开发者日志04|有人在看着你,也有人在议论你
大家好,我们是夏月工作室,这是第四篇开发日志。 上一期,小镇居民有了骨骼、身高胖瘦和 19 种表情。这一期,我们把重心从"做人"转到了"让世界活起来":居民会看、会偷、会传闲话,你也能和他们面对面聊天、递东西。 先回顾一下:这是一款什么样的游戏 一句话概括:运用涌现设计的 RPG 养成经营模拟游戏。 故事发生在一片云海上。人们住在一座座浮空的小岛上,房子像一节节旧车厢,往外看永远是云雾,只能隐约望
1 赞
《气味之城》开发日志#1|为什么"涌现"和猫是天作之合截图
《气味之城》开发日志#1|为什么"涌现"和猫是天作之合
大家好,我是一个人报名了 2026 聚光灯 21 天游戏创作挑战 的独立开发者。今年主题公布那一刻我就笑出了声——涌现。因为我已经想做这个游戏很久了: 《气味之城》:你不是猫神,你只是一只猫。 先说一个所有养猫人都懂的事实:你永远无法"教会"一只猫任何它自己不想学会的事。但你家猫可能自己学会了——听见冰箱开门就瞬移到厨房;你心情不好时过来踩奶;凌晨三点准时在你身上练马拉松。没人教过它,这些行为是它
3 赞
4 回复
00:34
《荒原复苏指南》开发日志④:关卡演示堂堂袭来!!截图
《荒原复苏指南》开发日志④:关卡演示堂堂袭来!!
- 人类曾因掌握元素合成技术而一度辉煌,又因滥用元素能量而逐渐从内里衰败。 - 30世纪80年代。社会文化充斥着激进乐观主义与庞大机械美学,在这里,污染和能源共生,幸福与痛苦并存。官方广播和宣传画里依旧在宣扬“科学将战胜一切”、“元素能量将再造新农田”的口号,而世界主城却已经因为污染过度而濒临崩溃、空间挤压严重。为了寻找新的生存空间与无污染能源,官方启动了“重构拓荒计划”。 - 玩家将作为前线拓展
14 赞
5 回复
【开发者日志5】蓝藻菌改变了大气结构,氧气既是毒药也是希望截图
【开发者日志5】蓝藻菌改变了大气结构,氧气既是毒药也是希望
好的大家好久不见了!在经历了一个周六日和周一的爆肝之后,现在的地球演化模拟器的进度终于迎来了伟大的突破!可算是做到了人类出现前! (当然有一大批进化历程都有cg概括过去的事情还请大家多多海涵了!剧情cg的时间不也挺好看的嘛) 目前的游戏嘛,按照关卡来算的话,大约可以分为四关吧。分别是: 隐生代 冥古宙 太古宙 以及元古宙和成冰纪。 其实本来的目标是想做到人类的未来发展的…因为最初的灵感来自攻壳机动
2 赞
《卡牌工业》开发日志 01|从“涌现”到产线对打截图
《卡牌工业》开发日志 01|从“涌现”到产线对打
大家好,我们正在用 Godot 做一个暂名《卡牌工业》的游戏。目前已经跑通了最小的生产与战斗循环,也做了两轮迭代。这篇先记录一下:面对“涌现”这个题目,我们讨论过什么,又为什么最后收敛到卡牌和工厂。 第一步:头脑风暴,涌现可以是什么? 刚看到“涌现”这个题目时,我们的想法几乎朝每个方向散开了。塔防、物理搭建、探索、解谜、经济系统、叙事,甚至增量游戏,都能让简单规则在玩家的操作中长出新的结果。再想下
00:39
【开发日志3】主场景与玩法无缝化衔接截图
【开发日志3】主场景与玩法无缝化衔接
大家好我是鸭。这里是墨江里的一群鸭,嘎嘎嘎~ 今天主要时间用来搭建主场景了,感觉有点浪费时间啊……理论上来说要进入到搜打撤玩法的unity场景搭建了。 不想打字了,大家看看画面表现效果吧~ #TapTap聚光灯独立游戏
11 赞
1 回复
《梦灵》开发记录:想做一款可自由构筑角色,爽快连招战斗的战棋截图
《梦灵》开发记录:想做一款可自由构筑角色,爽快连招战斗的战棋
#聚光灯gamejam开发者日志 #TapTap聚光灯独立游戏 #聚光灯 《梦灵》开发记录:想做一款可自由构筑角色,爽快连招战斗的回合制战棋…… 主题是涌现,灵感源自于《神界原罪》欢乐堡地下竞技场的PVP模式,自己和小伙伴经常跑团的时候,做过很多幻象的战斗场景,我自己也希望战斗能多一些未知和临场互动,让观察环境、判断对手、利用场景成为重要决策。个人认为,一个战斗系统足够好玩的前提,不是添加各种职业
2 赞
00:10
群迹·上取其下,下取其上截图
群迹·上取其下,下取其上
#聚光灯gamejam开发者日志 向大家汇报一下今日进度,目前在和蚁群的默认移动算法进行斗智斗勇。或许是我的AI对蚂蚁有别样的理解,其实最初写出的方案更接近于围绕着恒星公转的行星。 哦我还以为文章里可以插入多支视频视频,想要展示一些其它的运动方式,可惜了。那么就简单在上方传一个比较典型的,有点类似于蟑螂的运行方式。 目前仍在解决蚁群的随机运动,和玩家可操纵性之间的平衡问题。以及如各位所见,目前的
3 赞
1 回复
《我真没让他们建城啊!》开发者日志 06截图
《我真没让他们建城啊!》开发者日志 06
06 让那条链被看见了。 但玩家看完之后,问了一个更难的问题:看完了,然后呢? 一局结束,一切归零;一门知识学会,那个按钮就死了。 今天做的事,是给每一样东西接上下文。 日期: 2026-10-14 当前进度: 补上缺失的外层循环(转生/道基);知识从二值开关升级为可深造、可组合、可跨局继承;修复一个 0.75% 概率的地图崩溃;首次打通本地预览验证 写在前面:两条反馈,一个共同的字 06 收尾时
3 赞
2 回复
00:30
《失心》游戏开发者日志01|游戏UI迭代及实机演示截图
《失心》游戏开发者日志01|游戏UI迭代及实机演示
进入《失心》之前,玩家首先看到的是我们工作室 UNLOOK 的标识。我们将原来的标识转成 SVG,并让其中的红色瞳点转动、观察,再逐步显露完整字形,希望这个短暂的开场能带出一点好奇和不安。 这次《失心》的开局 UI,我们围绕小灵通(因为游戏的主要交互道具就是小灵通)做了几轮调整,希望玩家从打开游戏开始,就能感受到故事里的年代和气氛(故事年代背景为2000s)。 早期版本先确定了一个方向:把菜单放进
13 赞
10 回复