private static IEnumerable <SusceptibleRigidbody2D> GetSusceptibleBodies(ForceKind kind) { // TODO: cache 'em, cache em all! var bodies = GameObject.FindObjectsOfType <Rigidbody2D> (); foreach (var body in bodies) { var material = ForceReceiver.GetMaterial(body.gameObject); float influence = material.GetInfluence(kind); if (influence == 0) { continue; } yield return(new SusceptibleRigidbody2D(body, influence, material)); } }
void OnCollisionEnter(Collision collision) { if (collision.gameObject.layer != LayerMask.NameToLayer("Destructable")) { return; } ForceReceiver receiver = collision.gameObject.GetComponent <ForceReceiver>(); if (receiver != null) { receiver.OnHit(Velocity); } // print("Hit with force: " + Velocity + " magnitude: " + Velocity.magnitude); // Debug. // foreach (ContactPoint contact in collision.contacts) // { // Debug.DrawRay(contact.point, contact.normal, Color.white, 1f); // } }
private void ApplyToBodies(float timeFactor) { var ignoreSelfCollisionPredicate = Spatial.IgnoreSelfCollisionPredicate(rigidbody2D); // TODO: consider using CircleCollider2D trigger. I don't know how much faster trigger will be. var contactsByBody = Spatial.GetCircleContactsByBody( Origin, Radius, 0, Radius, hit => hit.collider.attachedRigidbody == null || ignoreSelfCollisionPredicate(hit), NumSweepDirections, LayerMask ); #if UNITY_EDITOR lastFrameContacts = contactsByBody; #endif foreach (var bodyAndContacts in contactsByBody) { var body = bodyAndContacts.Key; var bodyContacts = bodyAndContacts.Value; float influence = ForceReceiver.GetInfluence(body.gameObject, Kind); if (influence == 0) { continue; } float forceAmount = PhysicsHelper.ConvertToNewtons(Amount, Mode, body.gameObject); forceAmount *= influence * timeFactor * AnimatedMultiplier; if (DecreaseWithDistance) { var contactForceFactors = new ContactForceFactor [bodyContacts.Count]; float maxDistanceFactor = float.NegativeInfinity; float distanceFactorSum = 0; for (int i = 0; i < bodyContacts.Count; i++) { var contact = bodyContacts [i]; float distanceFactor = 1 - contact.Distance / Radius; if (distanceFactor > maxDistanceFactor) { maxDistanceFactor = distanceFactor; } distanceFactorSum += distanceFactor; var cff = new ContactForceFactor(contact, distanceFactor); contactForceFactors [i] = cff; } forceAmount *= maxDistanceFactor; /* Sum of all contact factors multiplied * by following factorScale will be 1. */ float factorScale = 1 / distanceFactorSum; foreach (var cff in contactForceFactors) { var contact = cff.Contact; float distanceFactor = cff.Factor * factorScale; float contactForceAmount = forceAmount * distanceFactor; var forceVector = contact.Direction * contactForceAmount; if (SendForceMessage(body.gameObject, forceVector, contact.Point)) { body.AddForceAtPosition(forceVector, contact.Point); } } } else { forceAmount /= bodyContacts.Count; foreach (var contact in bodyContacts) { var forceVector = contact.Direction * forceAmount; if (SendForceMessage(body.gameObject, forceVector, contact.Point)) { body.AddForceAtPosition(forceVector, contact.Point); } } } } }