void ApplyForce(Collider2D other) { IForceObject forceObj = other.GetComponent <IForceObject>(); if (forceObj != null) { int id = other.gameObject.GetInstanceID(); if (!isUsed.ContainsKey(id)) { isUsed [id] = false; } if (!isUsed [id]) { float yValue = transform.up.y; if ((yValue > -0.09f) && (yValue < 0.09f)) { yValue = 0; } float xValue = transform.up.x; if ((xValue > -0.09f) && (xValue < 0.09f)) { xValue = 0; } Vector2 dir = new Vector2(xValue, yValue); if (dir.x != 0 && dir.y == 0) { isUsed [id] = forceObj.ApplyForce(dir.normalized, Force.x, ForceYWhenOnlyX, true, TimeNotInput); } else { isUsed [id] = forceObj.ApplyForce(dir.normalized, Force.x, Force.y, true, TimeNotInput); } if (isUsed [id]) { anim.SetBool(animationName, true); audio.Stop(); audio.Play(); } if (ForceCallback != null) { ForceCallback(dir.normalized); } // isUsed [id] = true; } //Fix Loco else { isUsed [id] = false; anim.SetBool(animationName, false); } } }
/// <summary> /// Initialize the default values. /// </summary> protected override void Awake() { base.Awake(); m_GameObject = gameObject; m_Transform = transform; m_ForceObject = m_GameObject.GetCachedComponent <IForceObject>(); m_Rigidbody = m_GameObject.GetCachedComponent <Rigidbody>(); m_AttributeManager = GetComponent <AttributeManager>(); if (!string.IsNullOrEmpty(m_HealthAttributeName)) { m_HealthAttribute = m_AttributeManager.GetAttribute(m_HealthAttributeName); } if (!string.IsNullOrEmpty(m_ShieldAttributeName)) { m_ShieldAttribute = m_AttributeManager.GetAttribute(m_ShieldAttributeName); } m_AliveLayer = m_GameObject.layer; #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER m_NetworkInfo = m_GameObject.GetCachedComponent <INetworkInfo>(); m_NetworkHealthMonitor = m_GameObject.GetCachedComponent <INetworkHealthMonitor>(); if (m_NetworkInfo != null && m_NetworkHealthMonitor == null) { Debug.LogError("Error: The object " + m_GameObject.name + " must have a NetworkHealthMonitor component."); } #endif if (m_Hitboxes != null && m_Hitboxes.Length > 0) { m_ColliderHitboxMap = new Dictionary <Collider, Hitbox>(); for (int i = 0; i < m_Hitboxes.Length; ++i) { m_ColliderHitboxMap.Add(m_Hitboxes[i].Collider, m_Hitboxes[i]); } m_RaycastHits = new RaycastHit[m_MaxHitboxCollisionCount]; m_RaycastHitComparer = new Utility.UnityEngineUtility.RaycastHitComparer(); } EventHandler.RegisterEvent(m_GameObject, "OnRespawn", OnRespawn); }
/// <summary> /// Do the explosion. /// </summary> /// <param name="damageAmount">The amount of damage to apply to the hit objects.</param> /// <param name="impactForce">The amount of force to apply to the hit object.</param> /// <param name="impactForceFrames">The number of frames to add the force to.</param> /// <param name="originator">The originator of the object.</param> public void Explode(float damageAmount, float impactForce, int impactForceFrames, GameObject originator) { Health health = null; Rigidbody colliderRigidbody = null; IForceObject forceObject = null; var hitCount = Physics.OverlapSphereNonAlloc(m_Transform.position, m_Radius, m_CollidersHit, m_ImpactLayers, QueryTriggerInteraction.Ignore); #if UNITY_EDITOR if (hitCount == m_MaxCollisionCount) { Debug.LogWarning("Warning: The maximum number of colliders have been hit by " + m_GameObject.name + ". Consider increasing the Max Collision Count value."); } #endif for (int i = 0; i < hitCount; ++i) { // A GameObject can contain multiple colliders. Prevent the explosion from occurring on the same GameObject multiple times. if (m_ObjectExplosions.Contains(m_CollidersHit[i].gameObject)) { continue; } m_ObjectExplosions.Add(m_CollidersHit[i].gameObject); // The base character GameObject should only be checked once. if ((forceObject = m_CollidersHit[i].gameObject.GetCachedParentComponent <IForceObject>()) != null) { if (m_ObjectExplosions.Contains(forceObject)) { continue; } m_ObjectExplosions.Add(forceObject); } // OverlapSphere can return objects that are in a different room. Perform a cast to ensure the object is within the explosion range. if (m_LineOfSight) { // Add a slight vertical offset to prevent a floor collider from getting in the way of the cast. var position = m_Transform.TransformPoint(0, 0.1f, 0); var direction = m_CollidersHit[i].transform.position - position; if (Physics.Raycast(position - direction.normalized * 0.1f, direction, out m_RaycastHit, direction.magnitude, m_ImpactLayers, QueryTriggerInteraction.Ignore) && !(m_RaycastHit.transform.IsChildOf(m_CollidersHit[i].transform) #if FIRST_PERSON_CONTROLLER // The cast should not hit any colliders who are a child of the camera. || m_RaycastHit.transform.gameObject.GetCachedParentComponent <FirstPersonController.Character.FirstPersonObjects>() != null #endif )) { // If the collider is part of a character then ensure the head can't be hit. var parentAnimator = m_CollidersHit[i].transform.gameObject.GetCachedParentComponent <Animator>(); if (parentAnimator != null && parentAnimator.isHuman) { var head = parentAnimator.GetBoneTransform(HumanBodyBones.Head); direction = head.position - position; if (Physics.Raycast(position, direction, out m_RaycastHit, direction.magnitude, m_ImpactLayers, QueryTriggerInteraction.Ignore) && !m_RaycastHit.transform.IsChildOf(m_CollidersHit[i].transform) && !m_CollidersHit[i].transform.IsChildOf(m_RaycastHit.transform) && m_RaycastHit.transform.IsChildOf(m_Transform) #if FIRST_PERSON_CONTROLLER // The cast should not hit any colliders who are a child of the camera. && m_RaycastHit.transform.gameObject.GetCachedParentComponent <FirstPersonController.Character.FirstPersonObjects>() == null #endif ) { continue; } } else { continue; } } } // The shield can absorb some (or none) of the damage from the explosion. var hitDamageAmount = damageAmount; #if ULTIMATE_CHARACTER_CONTROLLER_MELEE ShieldCollider shieldCollider; if ((shieldCollider = m_CollidersHit[i].transform.gameObject.GetCachedComponent <ShieldCollider>()) != null) { hitDamageAmount = shieldCollider.Shield.Damage(this, hitDamageAmount); } #endif // ClosestPoint only works with a subset of collider types. Vector3 closestPoint; if (m_CollidersHit[i] is BoxCollider || m_CollidersHit[i] is SphereCollider || m_CollidersHit[i] is CapsuleCollider || (m_CollidersHit[i] is MeshCollider && (m_CollidersHit[i] as MeshCollider).convex)) { closestPoint = m_CollidersHit[i].ClosestPoint(m_Transform.position); } else { closestPoint = m_CollidersHit[i].ClosestPointOnBounds(m_Transform.position); } var hitDirection = closestPoint - m_Transform.position; // Allow a custom event to be received. EventHandler.ExecuteEvent <float, Vector3, Vector3, GameObject, object, Collider>(m_CollidersHit[i].transform.gameObject, "OnObjectImpact", hitDamageAmount, closestPoint, hitDirection * m_ImpactForce, originator, this, m_CollidersHit[i]); if (m_OnImpactEvent != null) { m_OnImpactEvent.Invoke(hitDamageAmount, closestPoint, hitDirection * m_ImpactForce, originator); } // If the shield didn't absorb all of the damage then it should be applied to the character. if (hitDamageAmount > 0) { // If the Health component exists it will apply an explosive force to the character/character in addition to deducting the health. // Otherwise just apply the force to the character/rigidbody. if ((health = m_CollidersHit[i].gameObject.GetCachedParentComponent <Health>()) != null) { // The further out the collider is, the less it is damaged. var damageModifier = Mathf.Max(1 - (hitDirection.magnitude / m_Radius), 0.01f); health.Damage(hitDamageAmount * damageModifier, m_Transform.position, hitDirection.normalized, impactForce * damageModifier, impactForceFrames, m_Radius, originator, this, null); } else if (forceObject != null) { var damageModifier = Mathf.Max(1 - (hitDirection.magnitude / m_Radius), 0.01f); forceObject.AddForce(hitDirection.normalized * impactForce * damageModifier); } else if ((colliderRigidbody = m_CollidersHit[i].gameObject.GetCachedComponent <Rigidbody>()) != null) { colliderRigidbody.AddExplosionForce(impactForce * MathUtility.RigidbodyForceMultiplier, m_Transform.position, m_Radius); } } } m_ObjectExplosions.Clear(); // An audio clip can play when the object explodes. m_ExplosionAudioClipSet.PlayAudioClip(m_GameObject); Scheduler.Schedule(m_Lifespan, Destroy); }