I believe I have come across a bug in Unity. When using Rigidbody.AddExplosionForce() on a Rigidbody with an attached trigger Collider, the force that the object feels is affected by the size of the attached trigger, which seems unrealistic. I have tested this pretty thoroughly (see details below), but I thought I'd discuss it here before posting it to the official Issue Tracker, in case this is actually intended behavior.
SETUP
- Empty scene with a Main Camera and Directional Light
- Add a 3x3 Plane for the ground (GameObject > 3D Object > Plane)
- Add a Cube (GameObject > 3D Object > Cube) at the origin. Attach a Rigidbody to it and keep all defaults, but set its constraints to "Freeze Position" along X and Z axes, and Freeze Rotation on all axes. Attach a SphereCollider and set its "Is Trigger" checkbox. This Cube will be the "target" of our explosions.
- Add an empty GameObject at position (0, -2, 0). Attach the Exploder script (see code below). Set this Exploder's "Target" property to the Cube object, set Explosion Force to 2, and UpwardsModifier to 2. This object will be the "initiator" of our explosions.
- We will vary the radius of the Cube's trigger SphereCollider, and the ExplosionRadius of the Exploder. Every time we initiate an explosion, we record the highest y-level obtained by the cube (logged to the Console by the Exploder script). For every trigger-explosion-radii setup, we record from 10 explosions. For consistency, only the first explosion from every run of the game should be recorded.
- Our radii setups will be:
1) Cube - 1, Exploder - 2
2) Cube - 1, Exploder - 4
3) Cube - 1, Exploder - 10
4) Cube - 4, Exploder - 2
5) Cube - 5, Exploder - 2
6) Cube - 4, Exploder - 4
7) Cube - 5, Exploder - 10 - Below is a screenshot of this setup on my machine:
RESULTS
I ran the above setups on my machine, and my results are reported in the image below. The table gives the minimum, median, and maximum values of the max heights obtained for each setup, along with the first and second quartiles, range, and interquartile-range (IQR). The three charts below that are box-and-whisker plots. The left plot shows the effect of varying the explosion's radius on the Rigidbody cube's max height, the middle plot shows the effect of varying the trigger's radius, and the right plot shows the effect of changing how the explosion/trigger spheres overlap (discussed below).
DISCUSSION
The goal of the above setups was to demonstrate that, when using Rigidbody.AddExplosionForce() on a Rigidbody with an attached trigger Collider, the magnitude of the explosion force felt by the Rigidbody is directly proportional to the radius of that trigger. We would expect that a Rigidbody positioned x units away from an explosion will experience the same force, no matter the size of an attached trigger volume, but this does not appear to be the case.
The left plot above shows the affect on the Rigidbody's max height of varying the explosion's radius. These setups varied the explosion radius from 1 to 10 units, and the max height increased from a median of 1.12 to 11.02 units. Larger explosions clearly achieved greater heights, which is expected. Interestingly, the variation in max height also seems to increase with larger explosions, with the IQR increasing from 0.50 to 6.22 units.
The middle plot shows the affect on the max height of varying the radius of the trigger Collider attached to the Rigidbody. These heights should have been unaffected by the trigger's radius, because the explosion radius stayed the same. However, the height achieved by the Rigidbody increased dramatically when its trigger was made larger. The trigger radius was varied from 1 to 5 units, and the max height increased from a median of 1.12 to 78.71 units. This effect was even larger than for varying the explosion's radius! As in the left plot, increasing the trigger radius also seemed to increase variation in the cube's max height, raising the IQR from 0.50 to 20.66 units.
The right plot groups setups 1, 2, 4, and 6 according to the overlap of the explosion's sphere and the trigger's sphere, as beautifully illustrated below. In Setup 1, both spheres overlapped, but neither sphere overlapped the center of the other sphere. In Setup 2 (and 3), the explosion sphere overlapped the center of the cube. In Setup 4 (and 5), the cube's trigger sphere overlapped the center of the explosion. In setup 6 (and 7), both spheres overlapped the center of the other sphere. Clearly, the cube's max height increased when either sphere overlapped the center of the other sphere. This effect was greater when the trigger overlapped the center of the explosion (median of the max height increased from 1.12 to 15.93 units when the trigger overlapped, but only to 5.10 when the explosion overlapped). When both spheres overlapped the other sphere's center in Setup 6, the max height reached about the same level as for Setup 4 (median of 16.05 units) but variation was greater (IQR of 15.20 vs 7.25 units).
In summary, increasing the size of a trigger volume attached to a Rigidbody increases the effect on it by explosion forces. To me, this seems like non-physical, buggy, behavior. I have not tested the effects of using a trigger Collider other than a SphereCollider, however. Also, it is worth noting that the cube experienced a force even in Setup 1, when the explosion sphere did not overlap the cube's center. Disabling the cube's SphereCollider removed these explosion affects, as would be expected. Thus, adding a trigger to a Rigidbody can make it feel explosion forces that it wouldn't otherwise. This seems like very unrealistic behavior! It was also surprising to me how much variation I saw in the Rigidbody's max height under identical explosion conditions. I can only guess that Nvidia's PhysX engine (which Unity uses) adds some randomness to every physical interaction.
EXPLODER CODE
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;
}
}
}
EDIT: Replaced all Physics.ApplyExplosionForce instances with Rigidbody.AddExplosionForce