下载 App
10/16案例分享
【案例分享】四个「完全静默」的引擎陷阱:不报错、不崩、画面正常,但功能就是没有
一句话结论
最耗时间的 bug 不是报错的那些,是「什么都没发生」的那些。
下面 7 条全部经实测验证,其中 4 条完全静默 —— 不报错、不崩、画面正常,只是你写的功能根本没生效。每条都给出症状、根因、修法和验证数据。
陷阱 1:3D 角色控制器必须用 KinematicCharacterController
症状:角色跳跃后碰到墙壁侧面会卡住(挂墙),动不了。
错误做法:RigidBody + SetLinearVelocity。
正确做法:使用 KinematicCharacterController 组件。
-- 错误:用刚体直接推速度
local body = node:CreateComponent("RigidBody")
body:SetLinearVelocity(dir * speed)
-- 正确:用角色控制器
local kcc = node:CreateComponent("KinematicCharacterController")
为什么:刚体是物理模拟驱动的,角色控制是「我想要去哪」的意图驱动。用刚体做角色,墙面碰撞会按物理反弹/摩擦处理,人就被「粘」在墙上了。
陷阱 2:KCC 不能单独使用,必须四件套(最容易踩的一条)
症状:角色不走、不受重力、无任何报错 —— 完全静默失效。
错误做法:只创建 KinematicCharacterController 就调 SetWalkDirection。
正确做法:必须按顺序凑齐四件套:
-- 1. 先建凸形碰撞形状(胶囊)
local shape = node:CreateComponent("CollisionShape")
shape:SetCapsule(radius, height)
-- 2. 再建 KCC
local kcc = node:CreateComponent("KinematicCharacterController")
-- 3. 配 CharacterComponent —— 负责把物理位置写回 node
local cc = node:CreateComponent("CharacterComponent")
第三件是大多数人漏掉的:没有 CharacterComponent,物理层算出来的位置不会写回 node —— 于是角色在物理世界里确实在走,但视觉上永远不动。
验证来源:引擎 issue #1907 调查(V 探针 + surfaceless 截图实测)。
排查提示:遇到「物理在动但看不见」,先查有没有把结果写回节点的组件。物理层和渲染层之间的同步不是自动的。
陷阱 3:SetEnabled(false) 藏不住子节点的渲染组件
症状:调用 node:SetEnabled(false) 后,子节点上的 StaticModel / AnimatedModel 仍然可见。
根因:Component:IsEnabledEffective() 只检查直接父节点的 enabled 状态,不递归检查祖先节点。
修:
-- 错误:只禁用父节点,子节点组件仍然渲染
employee.node:SetEnabled(false)
-- 正确:递归禁用整个子树
employee.node:SetDeepEnabled(false)
适用场景:有子节点层级结构的对象(角色、复合物体等)。如果一个对象是「父节点 + 一堆子节点挂模型」,那就要用 Deep 版本。
陷阱 4:正交相机的 orthoSize 有个 0.5 因子
症状:等距视角项目里,画面缩放对不上 —— 按算出来的值设置,实际显示差一倍。
根因:orthoSize 代表视野全高,但引擎内部用 orthoSize * 0.5 作为半高参与计算。
-- 想让可视高度为 H,应该设:
camera.orthoSize = H * 0.5
这一条只是点到为止 —— 完整的坐标换算和「缩放到鼠标位置」补偿公式,我单独写了一篇深挖:Camera.cpp 源码依据、NDC 换算、完整可复制的两个函数。
陷阱 5:Collision Margin 对小物体过大
症状:硬币、棋子这类小物体的碰撞体比视觉模型大一圈,物体看起来「漂浮」。
根因:Bullet 默认 margin 是 0.04m,这个值是为米级物体(人形 1.8m)设计的。对厚度只有 0.03m 的硬币,margin 会让厚度翻倍还多。
修:
local shape = node:CreateComponent("CollisionShape")
shape:SetCylinder(diameter, height)
shape:SetMargin(0.01) -- 关键
实测数据(硬币厚度 0.03m):
margin 默认 0.04 → 碰撞厚度 0.11m,偏差 +267%
margin 0.01 → 碰撞厚度 0.05m,偏差 +67%
通用规则:物体越小,默认 margin 的误差占比越大。尺寸接近或小于默认 margin 时,必须显式设置。
陷阱 6:Rolling Friction + Cylinder 不兼容
症状:硬币倾斜后卡住不倒,或者被弹飞。
根因:Rolling Friction 是为轮子类侧面滚动(接触点稳定)设计的。硬币倾斜时是边缘接触,曲率极小,力矩计算异常。
修:保持 rollingFriction = 0(不设置)。
local body = node:CreateComponent("RigidBody")
body.friction = 0.7
body.angularDamping = 0.5
-- 不设置 rollingFriction(保持默认 0)
实测数据:
rollingFriction = 0 → 正常
rollingFriction = 0.05 → 偶尔卡住
rollingFriction = 0.25+ → 斜着不倒 / 弹飞
适用范围:硬币、圆盘等圆面朝上的扁平圆柱体。不适用于轮子类侧面滚动 —— 那种场景 Rolling Friction 正是你要的。
陷阱 7:排行榜返回的 playerId 是数字,不是字符串
症状:拿排行榜数据做字符串拼接/比较时出错。
根因:GetRankList 返回的 player 字段是 number 类型,容易默认它是 string。
修:
local idStr = tostring(entry.player)
这条属于「类型假设」类缺陷。跨接口拿数据时,先确认类型再操作,别按经验假设。
小物体物理的「黄金组合」
把陷阱 5 和 6 合起来,就是小物体验证过的标准配方:
local body = node:CreateComponent("RigidBody")
body.mass = 0.05
body.friction = 0.7
body.angularDamping = 0.3 -- 0.3 ~ 0.5
-- 不设置 rollingFriction
local shape = node:CreateComponent("CollisionShape")
shape:SetCylinder(1, 1)
shape:SetMargin(0.01) -- 关键
这些坑什么时候会找上你
这七条不是「任何项目都会踩」,它们各有触发条件。对号入座比通读更省时间:
陷阱 1、2(角色控制器四件套):做 3D 角色移动会遇到;2D 游戏或纯 UI 交互不用管
陷阱 3(SetEnabled 不递归):对象有子节点层级(角色、复合物体)会遇到;单个平铺节点不用管
陷阱 4(orthoSize 0.5 因子):用正交相机做等距视角且要手动算坐标会遇到;透视相机不用管
陷阱 5(Collision Margin):物体尺寸接近或小于 0.04m 会遇到;米级物体不用管
陷阱 6(Rolling Friction):圆面朝上的扁平圆柱体(硬币、棋子)会遇到;轮子类侧面滚动反而需要它
陷阱 7(playerId 类型):从排行榜接口取数据做字符串操作会遇到;只做数值比较不用管
一个通用的分界线:陷阱 5、6 只在小物体上出现。你做的是人形角色、场景道具这类米级物体,那两个默认值完全够用,改了反而可能不对。
反过来,陷阱 3 和 4 跟物体大小无关,只跟「结构」和「投影方式」有关 —— 子节点层级和正交投影,撞上就是撞上。
如果只记一条:「没反应」的时候,先确认「我的设置有没有被消费」,再调参数。这七条里有五条,本质上都是「设置没被消费」。
可迁移的经验
1. 「没反应」优先查「有没有生效」,而不是继续调参数。静默失效的四个陷阱,全都可以用这一条更快定位。
2. 组件之间有隐藏的依赖顺序。KCC 缺一个组件就完全不动,而且不报错 —— 遇到「配了但没用」,先查是不是缺配套组件。
3. 物理层和渲染层不自动同步。必须有一个组件负责写回。
4. 默认值是给「典型尺寸」调的。物体偏离典型尺寸越多,默认值越可能害你。
5. 跨接口拿数据先确认类型。
判断「生效了没」最省事的办法,是把中间状态打印出来 —— 比如每帧打印角色 node 的坐标:如果坐标在变而画面不动,那就是「没写回」;如果坐标都不变,那就是「物理没在算」。一行 print 能省掉几小时瞎猜。
星火编辑器-新手教程-关于多游戏模式的配置和触发的获取截图
星火编辑器-新手教程-关于多游戏模式的配置和触发的获取
HELLO 大家好,我是阿木木牧。最近第一版的内部小范围(几人)第一个图的测试已经结束了。 整体游戏以装备数值的崩坏而告终~ (虽然大家都很欢快。。。) 现在准备开始开发下个阶段的内容啦,就是将游戏模式拆分出来。分成单人模式,多人组队模式(合作PVE),多人匹配模式(对抗模式)。那么,怎么配置呢?说来也很简单哈~ 1,在游戏编辑器中,数据编辑器,找到地图设置。 2,编辑地图设置。比如我希望最大数量
14 赞
3 回复
不支持当前设备截图
不支持当前设备
荣耀400pro
2 赞
3 回复
00:18
修复一下这个挂起过。有概率用不了的bug吧截图
修复一下这个挂起过。有概率用不了的bug吧
太绝望了[表情_豹哭][表情_豹哭][表情_豹哭][表情_豹哭]
1 赞
1 回复
05:19
1截图
1
1.完成后,获得信用点的增益依旧有效,可以卡无限信用点。理论上 2.部分天赋和在一起可以实现永续,那些天赋,我下一个发,因为只能传一个视频。 3.卡,人多点就卡,知道卡死,但是手机不会卡就游戏卡
2 赞
无须申请,星火编辑器现已公测开放下载截图
无须申请,星火编辑器现已公测开放下载
—————————————————— 各位关注星火编辑器的小伙伴: 感谢大家一直以来对编辑器支持! 破晓已去,曙光降临! 星火编辑器现已开启公测! · 关于下载和资格申请 现已无需申请,请去下面的官方首页直接下载! 缘起测试是星火编辑器自诞生以来第一次对外测试! 从2022年八月开始到十一月,历时三个月。 缘起之后缘聚测试,历时又七个月! 缘聚之后,破晓降临,历时又十二个月! 曾经微弱的星火现已渐
官方
331 赞
375 回复
00:11
人物有小概率会卡着不往前走截图
人物有小概率会卡着不往前走
3 赞
1 回复