Beispiel #1
0
        /// <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.
                        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);
        }