private void FixedUpdate() { for (int i = 0; i < continousCollisionContacts.Count; i++) { if (!continousCollisionContacts[i].IsAlive) { continousCollisionContacts.RemoveAt(i); i--; } else { SpeculativeCollisionContact c = continousCollisionContacts[i]; c.Lifetime -= 1; continousCollisionContacts[i] = c; } } }
protected void processSpeculativeCollision(TCollision collision) { int collisions = 0; //Loop over all contacts of the collision for (int i = 0; i < collision.ContactCount; i++) { TContact contactPoint = collision.GetContact(i); IImpactObject thisObject = getImpactObject(contactPoint.ThisObject); if (thisObject != null) { SpeculativeCollisionContact c = new SpeculativeCollisionContact() { RelativeContactPoint = thisObject.GetContactPointRelativePosition(contactPoint.Point), Lifetime = _contactPointLifetime }; //The relative position of the contact point serves as a unique identifier //So we can keep track of contact points between frames //If there is no existing point with the same relative position (within a threshold), then it is a "new" contact point. //We then process the point, basically mimicking an OnCollisionEnter message. int existingIndex = continousCollisionContacts.FindIndex(e => (e.RelativeContactPoint - c.RelativeContactPoint).sqrMagnitude < _contactPointComparisonThreshold); if (existingIndex == -1) { continousCollisionContacts.Add(c); if (collisions < MaxCollisionsPerFrame) { processCollisionContact(collision, contactPoint); collisions++; } } else { SpeculativeCollisionContact existingContact = continousCollisionContacts[existingIndex]; existingContact.Lifetime = _contactPointLifetime; continousCollisionContacts[existingIndex] = existingContact; } } } }