using UnityEngine; namespace DestroyIt { /// /// Attach this to any rigidbody object that acts as a projectile and may collide with /// Destructible objects. This script will play particle effects when the object hits /// something, and will do damage to Destructible objects. /// [RequireComponent(typeof(Rigidbody))] public class RigidbodyProjectile : MonoBehaviour { public HitBy weaponType = HitBy.Cannonball; [Tooltip("Impact velocity must be at least this amount to be detected as a hit.")] public float minHitVelocity = 10f; private Rigidbody rbody; private Vector3 lastVelocity; public void OnEnable() { rbody = GetComponent(); } public void FixedUpdate() { lastVelocity = rbody.velocity; } public void OnCollisionEnter(Collision collision) { // Check that the impact is forceful enough to cause damage if (collision.relativeVelocity.magnitude < minHitVelocity) return; if (collision.contacts.Length == 0) return; Collider other = collision.contacts[0].otherCollider; // Play hit effects HitEffects hitEffects = other.gameObject.GetComponentInParent(); if (hitEffects != null && hitEffects.effects.Count > 0) hitEffects.PlayEffect(weaponType, collision.contacts[0].point, collision.contacts[0].normal); // Apply impact damage to Destructible objects without rigidbodies // Only do this for the first active and enabled Destructible script found in parent objects // Special Note: Destructible scripts are turned off on terrain trees by default (to save resources), so we will make an exception for them and process the collision anyway Destructible[] destObjs = other.gameObject.GetComponentsInParent(false); foreach (Destructible destObj in destObjs) { if (!destObj.isActiveAndEnabled && !destObj.isTerrainTree) continue; // ignore any disabled destructible terrain trees if (destObj.GetComponentInParent() != null) continue; // ignore any destructible objects that have DestructibleParent scripts above them, that system already handles rigidbody collisions if (other.attachedRigidbody == null || other.attachedRigidbody.GetComponent() == null) { if (collision.relativeVelocity.magnitude >= destObj.ignoreCollisionsUnder) { destObj.ProcessDestructibleCollision(collision, gameObject.GetComponent()); rbody.velocity = lastVelocity; break; } } } // Check for Chip-Away Debris ChipAwayDebris chipAwayDebris = collision.contacts[0].otherCollider.gameObject.GetComponent(); if (chipAwayDebris != null) chipAwayDebris.BreakOff(collision.relativeVelocity * -1, collision.contacts[0].point); } } }