我相信我在Unity中遇到过一个错误。在带有附加触发器碰撞器的Rigidbody上使用Rigidbody.AddExplosionForce()时,对象感觉到的力受附加触发器的 size 的影响,这似乎是不现实的。我已经对此进行了彻底的测试(请参阅下面的详细信息),但我认为在将其发布到官方问题跟踪器之前我会在此进行讨论,以防这是实际的预期行为。
我在我的机器上运行了上述设置,我的结果报告在下面的图片中。该表给出了每个设置获得的最大高度的最小值,中值和最大值,以及第一和第二四分位数,范围和四分位数间距(IQR)。下面的三个图表是box-and-whisker plots。左图显示了改变爆炸半径立方体最大高度的爆炸半径的效果,中间的图显示了改变触发器半径的效果,右图显示了改变触发器半径的效果。改变爆炸/触发球体重叠的方式(下面讨论)。
上述设置的目的是证明,当在具有附加触发器碰撞器的Rigidbody上使用Rigidbody.AddExplosionForce()时,Rigidbody感受到的爆炸力的大小与该触发器的半径成正比。我们可以预期,无论连接的触发器体积大小如何,位于远离爆炸的 x 单位的Rigidbody都会经历相同的力,但事实并非如此。
上面的左图显示了改变爆炸半径的Rigidbody最大高度的影响。这些设置将爆炸半径从1到10个单位变化,最大高度从中位数1.12增加到11.02个单位。较大的爆炸明显达到了更高的高度,这是预期的。有趣的是,最大高度的变化似乎随着爆炸的增加而增加,IQR从0.50增加到6.22单位。
中间图显示了更改连接到Rigidbody的触发器碰撞器半径的最大高度的影响。这些高度应该不受触发器半径的影响,因为爆炸半径保持不变。然而,当Rigidbody的触发器变大时,Rigidbody实现的高度显着增加 。触发半径从1到5个单位不等,最大高度从中位数1.12增加到78.71个单位。这种效果甚至比改变爆炸半径还要大!如左图所示,增加触发半径似乎也增加了立方体最大高度的变化,将IQR从0.50提高到20.66单位。
右图根据爆炸球体和触发球体的重叠分组设置1,2,4和6,如下图所示。在设置1中,两个球体重叠,但两个球体都没有与另一个球体的中心重叠。在设置2(和3)中,爆炸球体与立方体的中心重叠。在设置4(和5)中,立方体的触发球体与爆炸中心重叠。在设置6(和7)中,两个球体都与另一个球体的中心重叠。显然,当任一球体与另一球体的中心重叠时,立方体的最大高度增加。当触发器重叠爆炸中心时,此效果更大(当触发器重叠时,最大高度的中位数从1.12增加到15.93单位,但当爆炸重叠时仅增加到5.10)。当两个球体在设置6中与另一个球体的中心重叠时,最大高度达到与设置4相同的水平(中位数为16.05单位),但变化更大(IQR为15.20对比7.25单位)。
总之,增加连接到刚体的触发器体积的大小会增加爆炸力对它的影响。对我而言,这似乎是非物质的,错误的行为。但是,我没有测试使用除SphereCollider之外的触发器Collider的效果。此外,值得注意的是,即使在设置1中,当爆炸球体不与立方体的中心重叠时,立方体也经历了一个力。正如预期的那样,禁用立方体的SphereCollider会消除这些爆炸影响。因此,向刚体添加触发器可以使其感觉到爆炸力,否则它将不会。这似乎是非常不切实际的行为!同样令我惊讶的是,在相同的爆炸条件下,我在刚体的最大高度上看到了多少变化。我只能猜测Nvidia的PhysX引擎(Unity使用的)会为每次物理交互增加一些随机性。
using UnityEngine;
public class Exploder : MonoBehaviour {
// HIDDEN FIELDS
private float _highY = 0f;
private bool _moving;
// INSPECTOR FIELDS
public Rigidbody Target;
public float ExplosionForce;
public float ExplosionRadius;
public float UpwardsModifier;
// EVENT HANDLERS
private void Update() {
// Explode on click
bool clicked = Input.GetMouseButton(0);
if (clicked) {
if (Target != null)
Target.AddExplosionForce(ExplosionForce, transform.position, ExplosionRadius, UpwardsModifier, ForceMode.Impulse);
}
// Report the object's highest y-level
if (Target.velocity.sqrMagnitude > 0) {
_highY = Mathf.Max(_highY, Target.transform.position.y);
_moving = true;
}
else if (_moving) {
Debug.LogFormat("Highest Y: {0}", _highY);
_highY = 0f;
_moving = false;
}
}
}
编辑:用Rigidbody.AddExplosionForce替换所有Physics.ApplyExplosionForce实例