public void SpawnExplosion(Vector3 explosionPosition, Vector3 explosionNormal, GameObject ignoreObject, ExplosionSettings explosionConfig, bool clientOnly) { CreateVisualExplosion(explosionPosition, explosionNormal, explosionConfig.explosionClass); DoLogicalExplosion(explosionPosition, ignoreObject, explosionConfig); }
private void DoShakeForExplosion(Vector3 explosionPosition, ExplosionSettings explosionConfig) { // Do screen shake on main camera if (ScreenShakeController.s_InstanceExists) { ScreenShakeController shaker = ScreenShakeController.s_Instance; float shakeMagnitude = explosionConfig.shakeMagnitude; shaker.DoShake(explosionPosition, shakeMagnitude, m_ExplosionScreenShakeDuration, 0.0f, 1.0f); } }
private void DoShakeForExplosion(Vector3 explosionPosition, ExplosionSettings explosionConfig) { if (ScreenShakeController.Instance == null) { return; } var shaker = ScreenShakeController.Instance; var shakeMagnitude = explosionConfig.shakeMagnitude; shaker.DoShake(explosionPosition, shakeMagnitude, m_ExplosionScreenShakeDuration, 0.0f, 1.0f); }
// Create explosions on collision private void OnCollisionEnter(Collision c) { if (m_Exploded) { return; } //Determine the collision's normal, position, and which explosion definition to use based on how many bounces we have left. Vector3 explosionNormal = c.contacts.Length > 0 ? c.contacts[0].normal : Vector3.up; Vector3 explosionPosition = c.contacts.Length > 0 ? c.contacts[0].point : transform.position; ExplosionSettings settings = m_Bounces > 0 ? m_BounceExplosionSettings : m_ExplosionSettings; if (Explosion.s_InstanceExists) { Explosion em = Explosion.s_Instance; if (settings != null) { em.SpawnExplosion(transform.position, explosionNormal, gameObject, m_OwningPlayerId, settings, false); } Explosion.SpawnDebris(explosionPosition, explosionNormal, m_OwningPlayerId, c.collider, m_SpawnedDebris, m_RandSeed); } //If we're bouncing, reflect our movement direction, decay our force, reduce our number of bounces. if (m_Bounces > 0) { m_Bounces--; Vector3 refl = Vector3.Reflect(-c.relativeVelocity, explosionNormal); refl *= m_BounceForceDecay; refl += m_BounceAdditionalForce; // Push us back up m_CachedRigidBody.velocity = refl; // Temporarily ignore collisions with this object if (m_TempIgnoreCollider != null) { Physics.IgnoreCollision(GetComponent <Collider>(), m_TempIgnoreCollider, false); } m_TempIgnoreCollider = c.collider; m_TempIgnoreColliderTime = m_IgnoreColliderFixedFrames; } else { Destroy(gameObject); } m_Exploded = true; }
private void DoLogicalExplosion(Vector3 explosionPosition, GameObject ignoreObject, ExplosionSettings explosionConfig) { var colliders = Physics.OverlapSphere(explosionPosition, Mathf.Max(explosionConfig.explosionRadius, explosionConfig.physicsRadius), m_PhysicsMask); foreach (var struckCollider in colliders) { if (struckCollider.gameObject == ignoreObject) { continue; } var explosionToTarget = struckCollider.transform.position - explosionPosition; var explosionDistance = explosionToTarget.magnitude; var targetHealth = struckCollider.GetComponentInParent <IDamageObject>(); if (targetHealth != null && targetHealth.IsAlive && explosionDistance < explosionConfig.explosionRadius) { var normalizedDistance = Mathf.Clamp01((explosionConfig.explosionRadius - explosionDistance) / explosionConfig.explosionRadius); var damage = normalizedDistance * explosionConfig.damage; targetHealth.Damage(damage); } var physicsObject = struckCollider.GetComponentInParent <PhysicsAffected>(); var identity = struckCollider.GetComponentInParent <NetworkIdentity>(); if (physicsObject != null && physicsObject.enabled && explosionDistance < explosionConfig.physicsRadius && (identity == null || identity.hasAuthority)) { physicsObject.ApplyForce(explosionConfig.physicsForce, explosionPosition, explosionConfig.physicsRadius); } } DoShakeForExplosion(explosionPosition, explosionConfig); }
/// <summary> /// Perform logical explosion /// On server, this deals damage to stuff. On clients, it just applies forces /// </summary> private void DoLogicalExplosion(Vector3 explosionPosition, Vector3 explosionNormal, GameObject ignoreObject, int damageOwnerId, ExplosionSettings explosionConfig) { // Collect all the colliders in a sphere from the explosion's current position to a radius of the explosion radius. Collider[] colliders = Physics.OverlapSphere(explosionPosition, Mathf.Max(explosionConfig.explosionRadius, explosionConfig.physicsRadius), m_PhysicsMask); // Go through all the colliders... for (int i = 0; i < colliders.Length; i++) { Collider struckCollider = colliders[i]; // Skip ignored object if (struckCollider.gameObject == ignoreObject) { continue; } // Create a vector from the shell to the target. Vector3 explosionToTarget = struckCollider.transform.position - explosionPosition; // Calculate the distance from the shell to the target. float explosionDistance = explosionToTarget.magnitude; // Server deals damage to objects // if (isServer) { // Find the DamageObject script associated with the rigidbody. IDamageObject targetHealth = struckCollider.GetComponentInParent <IDamageObject>(); // If there is one, deal it damage if (targetHealth != null && //targetHealth.isAlive && explosionDistance < explosionConfig.explosionRadius) { // Calculate the proportion of the maximum distance (the explosionRadius) the target is away. float normalizedDistance = Mathf.Clamp01((explosionConfig.explosionRadius - explosionDistance) / explosionConfig.explosionRadius); // Calculate damage as this proportion of the maximum possible damage. float damage = normalizedDistance * explosionConfig.damage; // Deal this damage to the tank. if (damageOwnerId == struckCollider.GetComponentInParent <Shooting>().m_PlayerNumber) { myAcademy.AddRewardToPlayer(damageOwnerId, -1 * damage); } else { myAcademy.AddRewardToPlayer(damageOwnerId, damage); } targetHealth.SetDamagedBy(damageOwnerId, explosionConfig.id); targetHealth.Damage(damage); } } // Apply force onto PhysicsAffected objects, for anything we have authority on, or anything that's client only PhysicsAffected physicsObject = struckCollider.GetComponentInParent <PhysicsAffected>(); NetworkIdentity identity = struckCollider.GetComponentInParent <NetworkIdentity>(); if (physicsObject != null && physicsObject.enabled && explosionDistance < explosionConfig.physicsRadius && (identity == null || identity.hasAuthority)) { physicsObject.ApplyForce(explosionConfig.physicsForce, explosionPosition, explosionConfig.physicsRadius); } } DoShakeForExplosion(explosionPosition, explosionConfig); }
/// <summary> /// Create an explosion at a given location /// </summary> public void SpawnExplosion(Vector3 explosionPosition, Vector3 explosionNormal, GameObject ignoreObject, int damageOwnerId, ExplosionSettings explosionConfig, bool clientOnly) { /* * if (clientOnly) * { * CreateVisualExplosion(explosionPosition, explosionNormal, explosionConfig.explosionClass); * } * else if (isServer) * { * RpcVisualExplosion(explosionPosition, explosionNormal, explosionConfig.explosionClass); * } */ CreateVisualExplosion(explosionPosition, explosionNormal, explosionConfig.explosionClass); DoLogicalExplosion(explosionPosition, explosionNormal, ignoreObject, damageOwnerId, explosionConfig); }