You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取不含滑动分量的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:55:20