I think your heavy rigidbody idea is the best: since you’re already applying AddExplosionForce to each hit rigidbody, add an extra line of code to apply AddExplosionForce to the exploding object as well: use the original explosion force multiplied by hit object mass * adjust factor, the hit object’s position as the explosion center, and the original explosion radius - this will cheaply produce a very convincent reaction force.
This is an adaptation of the AddExplosionForce example:
var radius = 5.0;
var power = 10.0;
var reaction = 0.1; // adjust reaction factor
function Start () {
// Applies an explosion force to all nearby rigidbodies
var explosionPos : Vector3 = transform.position;
var colliders : Collider[] = Physics.OverlapSphere (explosionPos, radius);
for (var hit : Collider in colliders) {
if (hit && hit.rigidbody){
// apply explosion force to the hit object:
hit.rigidbody.AddExplosionForce(power, explosionPos, radius, 3.0);
// apply reaction force proportional to the hit object's mass:
rigidbody.AddExplosionForce(reaction * power * hit.rigidbody.mass, hit.transform.position, radius)
}
}
}
EDITED: When the static object is long like a wall, you can find the reaction force origin using some geometry (case 1 in the drawing below): do a Linecast from the explosion to the object’s center, project the vector hit point - explosion onto the surface normal to find the reaction vector, then add it to the explosion pos: this returns the reaction origin in the wall plane. But what if the explosion is beyond the wall (case 2)? To detect this, you can do a short raycast to the reaction origin plus a little distance (0.5m, for instance) - if wall hit, use the calculated reaction origin; if not, explosion is beyond the wall, thus use the wall center as reaction origin. All this geometry may seem complicated, but is cheap: only when a static object is found you must use one linecast and one raycast, both short and inexpensive.
Since the treatment for static and movable objects must be different, you must know who’s who. The easiest way is to remove rigidbodies from the static objects: if the object hit has a rigidbody, AddExplosionForce to it (and the reaction force to the exploding object too, if you want); if no rigidbody, the object is static, thus just calculate the reaction origin and apply the reaction force.
This code considers static all objects without a rigidbody, and calculates the reaction origin like said above:
var pos : Vector3 = transform.position;
var colliders : Collider[] = Physics.OverlapSphere (pos, fieldRadius);
for (var hit : Collider in colliders) {
if (hit){
if (hit.rigidbody){ // movable object:
hit.rigidbody.AddExplosionForce(...); // apply force to object hit
// apply reaction force to exploding object as well, if you want
}
else { // no rigidbody means static object:
var pReact = hit.transform.position;
var hitP: RaycastHit;
Physics.Linecast(pos, pReact, hitP); // find the surface normal and hit point
// calculate vector from explosion to wall surface
var vReact = Vector3.Project(hitP.point - pos, hitP.normal);
// check if not beyond wall end:
if (Physics.Raycast(pos, vReact, vReact.magnitude + 0.5)){
pReact = pos + vReact; // ok: reaction origin is here
}
rigidbody.AddExplosionForce(fieldForce, pReact, fieldRadius, 0);
}
}
}
NOTE: If you need more control on which objects are static (and thus produce reaction) tag them as “Static” and check this in the else branch - this may be useful if you don’t want reaction from the ground, for instance.