private void Update() { if (preSoftenDestructible && destructibleObj != null && impactInfo != null) { destructibleObj.ApplyImpactDamage(impactInfo); impactInfo = null; destructibleObj = null; preSoftenDestructible = false; } }
public void ProcessBulletHit(RaycastHit hitInfo, Vector3 bulletDirection) { // Check if bullet struck dirt if (hitInfo.transform.GetComponent<Terrain>() != null) { ObjectPool.Instance.Spawn(Instance.strikeDirtPrefab, hitInfo.point, Quaternion.LookRotation(Vector3.up)); return; } // Check if bullet struck wood, concrete, glass, etc. through use of the TagIt system (Note: You can swap this out with your own multi-tagging system) TagIt tagIt = hitInfo.collider.GetComponent<TagIt>(); if (tagIt != null && tagIt.tags.Count > 0) { GameObject prefab; if (tagIt.tags.Contains(Tag.Wood)) prefab = Instance.strikeWoodPrefab; else if (tagIt.tags.Contains(Tag.Glass)) prefab = Instance.strikeGlassPrefab; else if (tagIt.tags.Contains(Tag.Metal)) prefab = Instance.strikeMetalPrefab; else if (tagIt.tags.Contains(Tag.Rubber)) prefab = Instance.strikeRubberPrefab; else if (tagIt.tags.Contains(Tag.Stuffing)) prefab = Instance.strikeStuffingPrefab; else // Default is concrete effect prefab = Instance.strikeConcretePrefab; ObjectPool.Instance.Spawn(prefab, hitInfo.point, Quaternion.LookRotation(hitInfo.normal)); } else // Default is concrete effect ObjectPool.Instance.Spawn(Instance.strikeConcretePrefab, hitInfo.point, Quaternion.LookRotation(hitInfo.normal)); // Apply damage if object hit was Destructible Destructible destObj = hitInfo.collider.gameObject.GetComponentInParent<Destructible>(); if (destObj != null) { ImpactInfo bulletImpact = new ImpactInfo() { Damage = Instance.bulletDamage, AdditionalForce = Instance.bulletForcePerSecond, AdditionalForcePosition = hitInfo.point, AdditionalForceRadius = .5f }; destObj.ApplyImpactDamage(bulletImpact); } Vector3 force = bulletDirection * (Instance.bulletForcePerSecond / Instance.bulletForceFrequency); // Apply impact force to rigidbody hit Rigidbody rbody = hitInfo.collider.attachedRigidbody; if (rbody != null) rbody.AddForceAtPosition(force, hitInfo.point, ForceMode.Impulse); // Check for Chip-Away Debris ChipAwayDebris chipAwayDebris = hitInfo.collider.gameObject.GetComponent<ChipAwayDebris>(); if (chipAwayDebris != null) chipAwayDebris.BreakOff(force, hitInfo.point); }
private void DoMeleeDamage() { Collider[] objectsInRange = Physics.OverlapSphere(meleeDamageArea.position, .75f); // Apply force and damage to colliders and rigidbodies in range of the explosion foreach (Collider col in objectsInRange) { // Ignore terrain colliders if (col is TerrainCollider) continue; // Check if weapon struck wood, concrete, glass, etc. through use of the TagIt system (Note: You can swap this out with your own multi-tagging system) TagIt tagIt = col.GetComponent<TagIt>(); if (tagIt != null && tagIt.tags.Count > 0) { GameObject prefab; if (tagIt.tags.Contains(Tag.Wood)) prefab = Instance.strikeWoodPrefab; else if (tagIt.tags.Contains(Tag.Glass)) prefab = Instance.strikeGlassPrefab; else if (tagIt.tags.Contains(Tag.Metal)) prefab = Instance.strikeMetalPrefab; else if (tagIt.tags.Contains(Tag.Rubber)) prefab = Instance.strikeRubberPrefab; else if (tagIt.tags.Contains(Tag.Stuffing)) prefab = Instance.strikeStuffingPrefab; else // Default is concrete effect prefab = Instance.strikeConcretePrefab; ObjectPool.Instance.Spawn(prefab, meleeDamageArea.position, Quaternion.LookRotation(meleeDamageArea.forward*-1)); } else // Default is concrete effect ObjectPool.Instance.Spawn(Instance.strikeConcretePrefab, meleeDamageArea.position, Quaternion.LookRotation(meleeDamageArea.forward*-1)); // Apply impact force to rigidbody hit Rigidbody rbody = col.attachedRigidbody; if (rbody != null) rbody.AddForceAtPosition(firstPersonController.forward*3f, firstPersonController.position, ForceMode.Impulse); // Apply damage if object hit was Destructible Destructible destObj = col.gameObject.GetComponentInParent<Destructible>(); if (destObj != null) { ImpactInfo meleeImpact = new ImpactInfo() { Damage = meleeDamage, AdditionalForce = 150f, AdditionalForcePosition = firstPersonController.position, AdditionalForceRadius = 2f }; destObj.ApplyImpactDamage(meleeImpact); } } }
//TODO: Combine these methods into one ApplyDamage overload, and make ExplosionInfo and ImpactInfo inherit from an interface or base class. public void ApplyImpactDamage(ImpactInfo impactInfo) { if (IsDestroyed || IsInvulnerable) return; // don't try to apply damage to an already-destroyed object. currentHitPoints -= impactInfo.Damage; CheckForObliterate(impactInfo.Damage); SetDamageLevel(); if (currentHitPoints <= 0) { IsDestroyed = true; PlayDamageLevelEffects(); // Advance to the next destructible object, passing in the leftover damage to apply to the next model and // the projectile, which may have force added to it so it can punch through the final (destroyed) object. if (canBeDestroyed) DestructionManager.Instance.ProcessDestruction(this, destroyedPrefab, impactInfo, IsObliterated); } }
/// <summary>Applies a generic amount of damage, with no special impact or explosive force./// </summary> public void ApplyDamage(int damageAmount) { //TODO: This method should call to ProcessDestruction with a general, non-specific DamageInfo. //HACK: Use ImpactInfo with no impact force for now. ImpactInfo generalDamage = new ImpactInfo() { Damage = damageAmount }; ApplyImpactDamage(generalDamage); }
/// <summary>Reapply force to the impact object (if any) so it punches through the destroyed object.</summary> public static void ReapplyImpactForce(ImpactInfo info, float velocityReduction) { if (info.ImpactObject != null && !info.ImpactObject.isKinematic) { info.ImpactObject.velocity = Vector3.zero; //zero out the velocity info.ImpactObject.AddForce(info.ImpactObjectVelocityTo * velocityReduction, ForceMode.Impulse); } }
public static void ProcessDestructibleCollision(this Destructible destructibleObj, Collision collision, Rigidbody collidingRigidbody) { // Ignore collisions if collidingRigidbody is null if (collidingRigidbody == null) return; // Ignore collisions if this object is destroyed. if (destructibleObj.IsDestroyed) return; // Check that the impact is forceful enough to cause damage if (collision.relativeVelocity.magnitude < 2f) return; if (collision.contacts.Length == 0) return; float impactDamage; Rigidbody otherRbody = collision.contacts[0].otherCollider.attachedRigidbody; // If we've collided with another rigidbody, use the average mass of the two objects for impact damage. if (otherRbody != null) { float avgMass = (otherRbody.mass + collidingRigidbody.mass) / 2; impactDamage = Vector3.Dot(collision.contacts[0].normal, collision.relativeVelocity) * avgMass; } else // If we've collided with a static object (terrain, static collider, etc), use this object's attached rigidbody. impactDamage = Vector3.Dot(collision.contacts[0].normal, collision.relativeVelocity) * collidingRigidbody.mass; impactDamage = Mathf.Abs(impactDamage); // can't have negative damage if (impactDamage > 1f) // impact must do at least 1 damage to bother with. { //Debug.Log("Impact Damage: " + impactDamage); //Debug.DrawRay(otherRbody.transform.position, collision.relativeVelocity, Color.yellow, 10f); // yellow: where the impact force is heading ImpactInfo impactInfo = new ImpactInfo() { ImpactObject = otherRbody, Damage = (int)impactDamage, ImpactObjectVelocityFrom = collision.relativeVelocity * -1 }; destructibleObj.ApplyImpactDamage(impactInfo); } }