如何获取不含滑动分量的Rigidbody2D碰撞速度以计算飞行车伤害?
飞行车碰撞伤害计算的滑动分量去除方案
问题描述
我制作了一辆飞行车,希望它与物体碰撞时损失HP。目前将车的RigidBody2D连接到如下函数实现该功能:
func _on_Car_body_entered(body): var force = linear_velocity.length() var dmg = pow(force / 100, 2) - 0.25 if dmg <= 0: return Health = Health - dmg
直接用速度向量的模长计算碰撞力,多数情况有效,但当飞行车高速水平移动且轻微触碰水平地面时,会因模长包含水平速度分量而产生大量不合理伤害。仅使用速度的Y分量虽能解决此场景问题,但会丢失水平碰撞的伤害,且扩展到多方向碰撞的开发成本过高。需要找到一种能从计算中去除滑动分量的方法。
解决方案:基于碰撞法向量计算有效冲击速度
核心思路是:碰撞的冲击伤害只和速度在碰撞法向的分量有关,切线方向的滑动分量不会产生冲击伤害,因此只需提取速度在碰撞法向量上的投影长度来计算伤害即可。
在Godot中,可以通过获取碰撞的法向量来实现这个逻辑,优化后的代码示例如下:
func _on_Car_body_entered(body): # 获取最近一次碰撞的详细信息 var collision_info = get_last_collision() if collision_info == null: return # 获取碰撞接触面的法向量(垂直于接触面的单位向量) var normal = collision_info.get_normal() # 计算速度在法向的投影长度,取绝对值忽略方向对伤害的影响 var impact_speed = abs(linear_velocity.dot(normal)) var dmg = pow(impact_speed / 100, 2) - 0.25 if dmg <= 0: return Health -= dmg
原理说明
- 碰撞法向量垂直于碰撞接触面,速度在这个方向上的分量才是真正导致冲击的核心部分,切线方向的滑动分量会被自然过滤。
- 比如高速水平移动轻碰地面时,地面的碰撞法向量向上(Y轴正方向),速度的Y分量很小,计算出的
impact_speed也会很小,不会产生大量伤害;而水平碰撞障碍物时,法向量为水平方向,速度的水平分量会被正常计算,保留了水平碰撞的伤害逻辑。
补充优化:碰撞冷却
如果担心单次碰撞触发多次信号导致重复扣血,可以添加短时间冷却逻辑:
var collision_cooldown = 0.2 # 冷却时间0.2秒 var last_collision_time = 0 func _on_Car_body_entered(body): # 检查是否处于冷却期 if OS.get_ticks_msec() / 1000 - last_collision_time < collision_cooldown: return last_collision_time = OS.get_ticks_msec() / 1000 var collision_info = get_last_collision() if collision_info == null: return var normal = collision_info.get_normal() var impact_speed = abs(linear_velocity.dot(normal)) var dmg = pow(impact_speed / 100, 2) - 0.25 if dmg <= 0: return Health -= dmg
内容的提问来源于stack exchange,提问作者Monset
相关产品推荐
相关产品推荐

