下载 App
回复时间
回复时间
手机用户7848649:
(4/5)
否则血条会读到上一帧的姿势。
用资源驱动的 rotationOffsetMeshSpace BlendSpace 路径,不受这个订阅顺序影响。
坑 4:模型替换后要重算偏移
AnimatedModel 组件被替换后:
- 重新计算 hpBarOffset
- 如果整个组件被换掉,重新执行一次 SetupHpBar()
如果你不需要血条跟着骨骼动
很多游戏的血条其实只要「悬浮在单位上方」就够了,不需要跟随头部朝向。
这种情况下有更省事的做法:不挂骨骼,直接跟随单位节点。
-- 每帧把血条摆到单位头顶
local pos = unitNode:GetWorldPosition()
hpBarNode:SetWorldPosition(Vector3(pos.x, pos.y + heightOffset, pos.z))
判断该用哪种:
需求:用什么
血条只是悬浮在头顶、不跟头转:跟随单位节点 + 固定高度偏移(简单)
血条要贴着头骨、跟着瞄准俯仰:骨骼挂点 + GetFinalWorldTransform()(上面的完整方案)
血条是屏幕空间 UI(永远面向相机):投影到屏幕坐标,用 UI 层绘制
大部分三消 / 塔防 / 俯视角游戏属于第一种 —— 先确认你真的需要骨骼挂点,
别为了「看起来专业」上一套复杂方案。
排查清单
现象:先查什么
血条比角色晚一帧:是不是在普通 Update 里读的?改到 SceneDrawableUpdateFinished
血条位置完全错乱:是不是误用了 offsetMatrix?改用 GetFinalWorldTransform()
偶尔崩溃:是不是跨帧缓存了 Bone?改成每帧重新获取
血条不跟着瞄准转:挂点 handler 是否排在 procedural AimOffset 之后订阅
换模型后血条跑飞:是否重新计算了 hpBarOffset
一句话总结
血条绑骨骼的关键不是「挂到骨骼下」,而是「每帧在 SceneDrawableUpdateFinished 里用 GetFinalWorldTransform() 取值」。
靠父子关系会晚一帧;靠缓存 Bone 会崩;靠 offsetMatrix 会错。
如果血条只要悬浮在头顶,根本不用碰骨骼 —— 跟随单位节点就够了
手机用户7848649:
(2/4)
local fsm = node:GetOrCreateComponent("AnimationStateMachine")
node:GetOrCreateComponent("AimOffset") -- 少了这个,AimOffset 配置不会生效
2. 在 FSM 里声明 AimOffset
{
"parameters": {
"AimPitch": { "type": "float", "default": 0.0, "min": -90.0, "max": 90.0 },
"AimYaw": { "type": "float", "default": 0.0, "min": -90.0, "max": 90.0 }
},
"aimOffset": {
"weight": 1.0,
"pitchParam": "AimPitch",
"yawParam": "AimYaw",
"blendSpace": "FSM/RifleStandAO.blendspace",
"boneMask": "UpperBody"
}
}
生效优先级是 state > layer > 顶层 —— 写在顶层会被 layer / state 级的同名配置覆盖。
排查「配了没反应」时,先确认没有更高优先级的配置把它顶掉。
3. 每帧把目标角度喂进去
-- 每帧调用:把「上半身应该朝向的角度」直接写进参数
fsm:SetFloat("AimYaw", targetYaw)
fsm:SetFloat("AimPitch", targetPitch)
这里的 targetYaw 是你算好的目标角度,不是增量。
AimOffset 是「把上半身摆到这个角度」,不是「每秒转多少度」——
所以它本身就没有"融合时间"这个概念,你喂什么角度,它就摆到什么角度。
如果你的目标是「完全去掉转身动画」
分两种情况:
情况 A:你要的是「瞬间对准」(射击游戏常见)