SanAndreasUnity/Assets/Scripts/Utilities/Damageable.cs

115 lines
2.8 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace SanAndreasUnity.Utilities
{
public class DamageInfo
{
public float amount = 0f;
public string damageType = null;
public Transform raycastHitTransform = null;
public Vector3 hitPoint = Vector3.zero;
public Vector3 hitNormal = Vector3.up;
public object attacker = null;
public object data = null;
}
public static class DamageType
{
public static readonly string
Bullet = "Bullet",
Explosion = "Explosion";
}
public class Damageable : MonoBehaviour
{
[SerializeField] private float m_health = 0f;
public float Health { get { return m_health; } set { m_health = value; } }
[SerializeField] private UnityEvent m_onDamage = new UnityEvent ();
2020-06-09 16:34:15 +00:00
public UnityEvent OnDamageEvent => m_onDamage;
public DamageInfo LastDamageInfo { get; private set; }
public void Damage (DamageInfo info)
{
this.LastDamageInfo = info;
2020-05-17 00:17:52 +00:00
F.RunExceptionSafe(() => m_onDamage.Invoke());
}
public void HandleDamageByDefault ()
{
DamageInfo info = this.LastDamageInfo;
this.Health -= info.amount;
if (this.Health <= 0f) {
Destroy (this.gameObject);
}
}
public static void InflictDamageToObjectsInArea(
Vector3 center, float radius, float damageAmount, AnimationCurve damageOverDistanceCurve, string damageType)
2020-06-21 16:21:15 +00:00
{
Collider[] overlappingColliders = Physics.OverlapSphere(center, radius);
2020-06-21 16:21:15 +00:00
var damagables = new Dictionary<Damageable, List<Collider>>();
2020-06-21 16:21:15 +00:00
foreach (var collider in overlappingColliders)
2020-06-21 16:21:15 +00:00
{
var damagable = collider.GetComponentInParent<Damageable>();
if (damagable != null)
2020-06-21 16:21:15 +00:00
{
if (damagables.ContainsKey(damagable))
{
damagables[damagable].Add(collider);
}
else
{
damagables.Add(damagable, new List<Collider>() { collider });
}
2020-06-21 16:21:15 +00:00
}
}
foreach (var pair in damagables)
2020-06-21 16:21:15 +00:00
{
Damageable damageable = pair.Key;
List<Collider> colliders = pair.Value;
2020-06-21 16:21:15 +00:00
// find closest point from all colliders
2020-06-21 16:21:15 +00:00
float closestPointDistance = float.MaxValue;
foreach (var collider in pair.Value)
{
Vector3 closestPointOnCollider = collider.ClosestPointOrBoundsCenter(center);
float distanceToPointOnCollider = Vector3.Distance(center, closestPointOnCollider);
if (distanceToPointOnCollider < closestPointDistance)
{
closestPointDistance = distanceToPointOnCollider;
}
}
// apply damage based on closest distance
float distance = closestPointDistance;
float distanceFactor = damageOverDistanceCurve.Evaluate(Mathf.Clamp01(distance / radius));
2020-06-21 16:21:15 +00:00
float damageAmountBasedOnDistance = damageAmount * distanceFactor;
F.RunExceptionSafe(() => damageable.Damage(new DamageInfo() { amount = damageAmountBasedOnDistance, damageType = damageType }));
2020-06-21 16:21:15 +00:00
}
}
}
}