下载 App

茄子变小瞬间变成了小的西红柿

05/083 浏览综合
现在我找到了关键线索。让我仔细分析这个 bug 的根因:
问题发生在 EnzymeParticle.StripPixel() 中(EnzymeParticle.lua:149-163):
lua
复制
-- 懒初始化:首次剥离时从渲染缓存深拷贝像素数据到敌人实例
if not target.instancePixels and renderModule_ then
    local shared = renderModule_.GetSpriteData(target.typeName)
    if shared and shared.pixels then
        target.instancePixels = {}
        for key, px in pairs(shared.pixels) do
            target.instancePixels[key] = { px[1], px[2], px[3], px[4] }
        end
        target.instanceGridSize = shared.gridSize
    end
end
当酶粒子首次剥离一个敌人的像素时,它会从 Render.GetSpriteData(target.typeName) 获取共享像素数据。然后看 Render.GetSpriteData:
lua
复制
function Render.GetSpriteData(typeName)
    return npcSpriteCache_[typeName]
end
这里 npcSpriteCache_ 是按 enemyType(如 "tomato", "eggplant" 等)来索引的。但问题在于 碎裂子体继承了错误的 typeName。
让我看看 Enemy.Split() 中的逻辑(Enemy.lua:165):
子体的 typeName 被设为 childTypeName = cfg.splitInto
子体的 instancePixels 是从父体像素深拷贝的
所以碎裂不是问题——子体已经正确继承了父体的像素。
再仔细看渲染侧的逻辑(Render.lua:1519):
lua
复制
local instancePixels = e.instancePixels
local spriteData = instancePixels and { gridSize = e.instanceGridSize, pixels = instancePixels }
                    or npcSpriteCache_[e.typeName]
关键:如果 e.instancePixels 为 nil,就会用 npcSpriteCache_[e.typeName] 作为 fallback。碎裂后子体的 typeName 是 splitInto 的值。让我查看 Config 中茄子的配置。
找到了关键线索。NPC 精灵绑定文件在 npc_sprites/_npc_bindings.json。让我检查绑定数据和 DraftBindings.lua 的加载逻辑。
现在我看到了完整的渲染逻辑。关键是在第 1517-1518 行:
lua
复制
local instancePixels = e.instancePixels
local spriteData = instancePixels and { gridSize = e.instanceGridSize, pixels = instancePixels }
                    or npcSpriteCache_[e.typeName]
分裂后的子体 typeName = childTypeName(如 "meat_mid")。如果子体没有 instancePixels,它会尝试用 npcSpriteCache_[e.typeName],即 npcSpriteCache_["meat_mid"]。
让我确认 NPC 绑定是否只绑定了顶层类型,没有绑定 _mid/_small 子类型。
现在我找到了 bug 的根因。让我确认一下完整的逻辑链:
Bug 根因分析:
Render.LoadNpcSprites(organId) 遍历 LevelManager.GetNpcBinding(organId) 的绑定映射 { [enemyType] = npcName }
NPC 绑定只绑定了顶层类型(如 "meat" → "茄子"),不会绑定 "meat_mid" 或 "meat_small" 等子类型
所以 npcSpriteCache_["meat"] = 茄子精灵,但 npcSpriteCache_["meat_mid"] = nil
非dish敌人的分裂路径(关键场景):
茄子作为 typeName="meat" 的非 dish 敌人被生成(通过 NPC binding 显示为茄子)
它没有 instancePixels(只有 dish 敌人或被酶剥离过的敌人才有)
渲染时使用 npcSpriteCache_["meat"] = 茄子 ✓
被咬碎时 Enemy.Split() 创建子体 typeName = "meat_mid"
Split 函数尝试获取 parentPixels:
enemy.instancePixels = nil(从未设置过)
回退到 Render.GetSpriteData("meat") = npcSpriteCache_["meat"] = 茄子像素 ✓
子体获得深拷贝的茄子像素 ✓
等等…这应该是可以工作的。让我再仔细检查 Split 中 parentPixels 不为 nil 时的路径——如果像素确实被继承了,那子体应该有 instancePixels,渲染时应该优先用它。
找到关键线索了!茄子的 category 是 "veggie"(蔬菜),映射到 "bread" 类型。所以:
茄子 → category=“veggie” → enemyType=“bread” → 渲染时用 npcSpriteCache_["bread"] = 茄子精灵
分裂后 → childTypeName = Config.EnemyTypes["bread"].splitInto = "bread_mid"
子体 typeName = "bread_mid"
现在关键问题:Split 中如果 enemy.instancePixels 为 nil(非 dish 普通食物),它从 Render.GetSpriteData("bread") 获取到 npcSpriteCache_["bread"] 的共享像素,深拷贝给子体。这个路径应该是对的…
但等等!还有另一个问题。让我确认一下 Beat 系统直接随机生成的敌人(不通过投喂管线的)——也就是用户说的截图中 Beat 1 的情况。如果是直接从 generateWaveComposition 随机生成的敌人,它们没有 foodData!
好,现在来看食物池中的 entry.foodData 是否包含 isDish 信息。在 InjectFoods 中,传入的 item 直接作为 foodData。这些来自 FoodPipeline 的食物项,如果是投喂的单食材(如茄子),isDish 为 false 或 nil,所以 Enemy.Spawn 时不会走 dish 分支,不会设置 instancePixels。
这意味着非 dish 的茄子:
typeName = "bread"(茄子 category=“veggie” → “bread”)
没有 instancePixels
渲染依赖 npcSpriteCache_["bread"] = 茄子精灵 ✓
Split 时从 Render.GetSpriteData("bread") 获取像素,深拷贝给子体 ✓
子体有 instancePixels = 深拷贝 ✓
理论上应该正常工作。让我检查另一种可能性——也许 NPC binding 中 "bread" 对应的不是茄子,而是其他什么东西?或者有多个 enemyType 绑到同一个 organ,而 "bread_mid" 有自己的绑定(到西红柿)?
NPC 绑定数据是在云端/运行时加载的,本地没有缓存。基于代码分析,我已经找到了 bug 的根因。让我总结并修复:
根因分析:
茄子 → category=“veggie” → enemyType="bread" → npcSpriteCache_["bread"] = 茄子精灵 ✓
分裂后子体 typeName = "bread_mid"
Split 函数中,非 dish 敌人 instancePixels = nil,需要从 Render.GetSpriteData("bread") 获取父体像素来深拷贝给子体
如果像素继承成功,子体有 instancePixels,渲染正确
如果像素继承失败(pcall require 时序问题,或 NPC sprites 还未加载完),子体没有 instancePixels,渲染回退到 npcSpriteCache_["bread_mid"] —— 如果 NPC 绑定中 bread_mid 映射到了"西红柿",就变成西红柿了!
修复方案:在子体上记录父体的 typeName,渲染时优先用父体的 NPC 精灵作回退。
根据上下文恢复记录,茄子变西红柿的精灵 bug 已经修复完毕并构建成功。
修复总结
根因:敌人分裂时,子体的 typeName 变成了 "bread_mid"(由 Config 的 splitInto 链决定),但 npcSpriteCache_["bread_mid"] 可能绑定了与父体 "bread" 不同的 NPC 精灵(西红柿),导致视觉上茄子瞬间变成了西红柿。
修复方案:通过 npcFallbackType 字段让分裂子体记住父体的原始 typeName,渲染和酶粒子系统优先使用父体的精灵:
文件 改动
Enemy.lua Split() 中为子体添加 npcFallbackType = enemy.npcFallbackType or enemy.typeName,支持多级分裂传递
Render.lua DrawSingleEnemy() 的精灵选择、hasSprite 检查、cacheKey 均改用 e.npcFallbackType or e.typeName
EnzymeParticle.lua StripPixel() 惰性初始化改用 npcFallbackType 查找共享精灵
EnzymeNpc.lua StripPixel() 同上修复
构建已通过,无报错。你可以预览测试一下茄子分裂后是否仍保持茄子/紫色碎块的外观。
【更新】新增驿站+远征地截图
【更新】新增驿站+远征地
官方
2 回复
【更新】平台新版本发布游戏变成了“预约”截图
【更新】平台新版本发布游戏变成了“预约”
今天更新之后,一直奇怪怎么看不到“热度”,变成了“预约” 后面才知道,需要去这里改为 提供游玩 【更新】 1、新增便签墙功能,每一局都有小故事 2、增加了自定义头像
3 赞
1 回复
🚪【权限申请】传送门截图
🚪【权限申请】传送门
需要把ID发到论坛里(ID在游戏右下角),管理员审批。 这里回帖ID就行
7 赞
131 回复
【看病得花多钱】这是我的一个想法,作为下一个版本的重要功能。
但目前苦于没有各地各级医院的收费数据,如果有朋友能随手告知一二,我都愿意收集起来,形成这个游戏体验功能。截图
【看病得花多钱】这是我的一个想法,作为下一个版本的重要功能。 但目前苦于没有各地各级医院的收费数据,如果有朋友能随手告知一二,我都愿意收集起来,形成这个游戏体验功能。
精华
2 赞
20 回复
牌面文字反复重新布局和渲染
调查结论 问题已查清:牌面文字本身没有异常,也不是 NanoVG 重复绘制。真正原因是每名玩家或 AI 投币后,客户端都会销毁并重新创建整个战斗 UI。 左右牌文字、牌框、顶部头像、底部状态栏都在同一棵 UI 树中。因此本来只需要更新底部投币槽,却连带让红框内的牌面文字反复重新布局和渲染,表现为“闪烁几下”。 直接证据 Client.BuildPlayingUI() 每次先销毁现有根节点: scr
官方
求密码id 如图截图
求密码id 如图
1 赞
1 回复
统一生成素材的话术模板
可以。根据前面对话,建议不要把所有素材塞进同一条模板,因为目前已经形成了两套用途不同、但能共享色彩语言的视觉体系: 抽象概念角色插画:用于“沉没成本、追涨接盘、社会懈怠”等概念角色。 圆形技能徽章图标:用于“紧急避险、控盘信号、护航珍贝”等游戏技能。 下面可以直接保存为项目的统一美术生成规范。 一、统一美术风格总纲 风格名称 金融寓言卡通风 通用风格关键词 卡通手绘风格,金融寓言与社会讽刺主题,粗
官方
UI 按键动画设计经验
从 GDScript (Godot Tween) 移植到 UrhoX Lua + raw NanoVG 的完整经验总结。 版本: v0.3.0 | 日期: 2026-07-28 重要:第 1~9 节是"设计理论 + 自建补间引擎"思路(适合理解原理)。 但在《抓周》这类 Boot/Router/EventBus 模板里实测落地时,靠 Update 驱动补间会让按钮不可见、nvgRGBA 整数色会
官方
【更新】增加了一些任务截图
【更新】增加了一些任务
我从故事便签墙中,看到了大多数玩家都在和野兽、疾病博弈中倒下 我这两天补充了一些任务,有关合成物品的为主 在此感谢大伙儿的积极反馈
1 赞
4 回复
任务
当前任务栏共设计了 2 个阶段、7 个任务: --- ### 襁褓 · 初识世界(5个) | # | 任务名 | 描述 | 完成条件 | |---|--------|------|----------| | 1 | 看见万物 | 开启你的人生初体验 | 初始体验包开出 3 张牌 | | 2 | 伸手触碰 | 拖动任意一张牌 | 拖动 1 次 | | 3 | 万物相遇 | 把一张牌放到另一张牌上 |
官方