【游戏功能】
一、一个总打不中的直线技能
灵魂冲击类直线技能上线后,命中率统计只有六成。看回放,怪明明站在路径上,波从它身边过去了。原因画出来一目了然:冲击波的判定线画在地面高度,而怪的受击区间在头胸——波从怪的膝盖以下掠过,脚底的坐标自然对不上躯干。视觉上玩家看见波贴着怪的头胸飞过却没结算,只会判定"这游戏的判定是坏的"。直线波的判定必须是一个竖直的带,不是一条线。
二、机制原理:头胸判定带
把直线技能的命中模型从"一条线"升级为"一条带":带的中心是全局要害高度,带高约六十六像素,上缘到头顶、下缘到腰腹。波的推进只看横向坐标,每帧检查所有横向距离小于三十像素且尚未命中的目标——竖直方向不用查,因为带高覆盖了站姿目标的全部躯干。穿透开关决定同一目标可否被多次结算:穿透关闭时命中第一个就终止推进,开启时一路贯到底。带内命中的另一个好处是表现层天然成立——波本来就是画在头胸高度横扫的,判定带和视觉带重合,玩家看见什么就相信什么。
fx-soulimpact
三、正确写法:判定带横扫(引擎侧)
local WAVE = {
SPEED = 800,
BAND_TOP = 96, -- 判定带上缘(相对脚底)
BAND_BOTTOM = 30, -- 下缘
HIT_RADIUS = 30, -- 横向命中半径
}
function soulImpact:Update(dt)
if not self._wave then return end
self._wave.x = self._wave.x + WAVE.SPEED * dt
for _, m in ipairs(scene:GetMonsters()) do
if self._pierce or not self._wave:HasHit(m) then
if math.abs(self._wave.x - m:GetX()) <= WAVE.HIT_RADIUS then
self._wave:MarkHit(m) -- 记录: 防穿透重复结算
m:OnHit(self._dmg)
if not self._pierce then
self._wave = nil -- 不穿透: 打到即止
return
end
end
end
end
if self._wave.x > scene:GetWidth() + 60 then self._wave = nil end
end
四、四个必须钉死的细节
五、心法:判定带是直线技能的身高
把"线"升级为"带"的思想适用于一切穿透类技能:横扫的刀气、贯穿的光束、推进的墙,它们的判定都该是一个有高度的区间而非一根线。带的高度引用全局要害协议,宽度引用技能自身的视觉宽度——判定带永远长在视觉的身上,这是直线技能从"偶尔打不中"到"指哪打哪"的全部秘密。
调试期还有个笨办法但极好用:把判定带的上下缘画成两条虚线常驻在场景里,测试和录屏一目了然,上线前删掉或降透明度即可。本篇演示里那两条紫色虚线就是这么回事——玩家看得见判定,才评得出手感;看不见判定的游戏,所有的"没打中"都会被记成"这游戏有问题"。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 一、先抛一个坑 同样是"放一片技能特效",为什么有的游戏炸二十个火球丝般顺滑,有的游戏炸五个就掉帧?直觉答案"…
【游戏功能】 一、一个职业选手的操作拆解 看高手第一视角录像,最费解的操作是:他打一下、退两步、再打一下,全程像在跳一支排练…
【游戏功能】 一、一个被浪费的冰冻 组里新人做了个冰法连招:冰冻命中后立刻接大火球,理论伤害翻倍。试玩却怪怪的——冰冻刚套上…
【游戏功能】 一、一次吓到自己的召唤 召唤兽系统的内测录像里有个名场面:道士按下召唤,屏幕上"啪"地多出一只金毛巨狼,没有地…
【游戏功能】 一、先抛一个坑 领域类技能最怕做成"一次性特效放完拉倒":冰环扩一圈、冻一下、结束——站在领域里的怪第二秒解冻…
【游戏功能】 一、一次只有挨打没有还手的守势 守势类技能首版的哀嚎最一致:"金环弹开了围攻,然后呢?"——然后没有然后。格挡…