aboutsummaryrefslogtreecommitdiff
path: root/Assets/Scripts/DamageVolumeSystem/DamageGenerator.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/Scripts/DamageVolumeSystem/DamageGenerator.cs')
-rw-r--r--Assets/Scripts/DamageVolumeSystem/DamageGenerator.cs159
1 files changed, 159 insertions, 0 deletions
diff --git a/Assets/Scripts/DamageVolumeSystem/DamageGenerator.cs b/Assets/Scripts/DamageVolumeSystem/DamageGenerator.cs
new file mode 100644
index 0000000..ca50a26
--- /dev/null
+++ b/Assets/Scripts/DamageVolumeSystem/DamageGenerator.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Serialization;
+
+namespace DamageVolumeSystem
+{
+ [Icon("Assets/Scripts/DamageVolumeSystem/Icon/DamageGenerator.png")]
+ [RequireComponent(typeof(BoxCollider))]
+ [ExecuteAlways]
+ public class DamageGenerator : MonoBehaviour
+ {
+ [HideInInspector] public DamageHost binding;
+
+ // 伤害
+ public int damage = 2500;
+
+ // 衰减曲线
+ public AnimationCurve falloffCurveByDistance = AnimationCurve.Linear(0, 1, 1, 0);
+ public AnimationCurve falloffCurveBySpeed = AnimationCurve.Linear(0, 1, 1, 0);
+
+ // 碰撞体
+ private BoxCollider _collider;
+
+ // 碰撞时发生伤害
+ public bool emitOnCollide = true;
+
+ // 扫描到的碰撞体
+ private readonly HashSet<DamageHost> _scannedHosts = new();
+
+ // 速度缩放
+ private float _speedScale;
+
+ // 上一帧的位置
+ private Vector3 _lastPosition;
+
+ private void Start()
+ {
+ _collider = GetComponent<BoxCollider>();
+ }
+
+ private void FixedUpdate()
+ {
+ var p = transform.position;
+ var distanceToLast = Vector3.Distance(p, _lastPosition);
+ var next = falloffCurveBySpeed.Evaluate(1 - Mathf.Clamp01(distanceToLast / 1.5f));
+ _speedScale = 0.5f + next * 2;
+
+ _lastPosition = p;
+ }
+
+ public void Update()
+ {
+#if UNITY_EDITOR
+ _collider.isTrigger = true;
+ _collider.center = Vector3.zero;
+ _collider.size = transform.lossyScale;
+#endif
+ }
+
+ private void OnTriggerEnter(Collider other)
+ {
+ var damageHost = other.GetComponent<DamageHost>();
+ if (damageHost != null && _scannedHosts.Add(damageHost))
+ {
+ // 碰撞时立刻产生伤害
+ if (emitOnCollide)
+ Emit();
+ }
+ }
+
+ private void OnTriggerExit(Collider other)
+ {
+ var damageHost = other.GetComponent<DamageHost>();
+ if (damageHost != null && _scannedHosts.Contains(damageHost))
+ {
+ _scannedHosts.Remove(damageHost);
+ }
+ }
+
+ public void Emit()
+ {
+ var pos = transform.position;
+
+ foreach (var scannedHost in _scannedHosts)
+ {
+ var selfGroup = binding?.group ?? 12;
+ if (selfGroup == scannedHost.group)
+ continue;
+
+ var posTarget = scannedHost.transform.position;
+ var distance = Vector3.Distance(pos, posTarget);
+ var percent = Mathf.Clamp01(distance / 2);
+
+ var direction = (posTarget - pos).normalized;
+
+ // 用衰减曲线重新映射百分比
+ var rePercent = falloffCurveByDistance.Evaluate(1 - percent);
+ var calcDamage = Mathf.RoundToInt(rePercent * damage * _speedScale);
+
+ Debug.Log($"[伤害生成器: {gameObject.name}] 对 {scannedHost.name} 造成 {calcDamage} 点伤害 (距离衰减 {percent} -> {rePercent}, 速度增益 {_speedScale})");
+ scannedHost.onDamageReceived.Invoke(new Damage
+ {
+ Group = binding?.group ?? 12,
+ Force = calcDamage,
+ Direction = direction,
+ });
+ }
+ }
+
+ # region Display
+
+ private void OnDrawGizmos()
+ {
+ var t = transform;
+ Gizmos.color = GetColorByGroupId(binding?.group?? 12);
+
+ // 画指向线
+ foreach (var scannedHost in _scannedHosts)
+ {
+ Gizmos.DrawLine(scannedHost.transform.position, t.position);
+ }
+
+ // 画生成框
+ Gizmos.matrix = t.localToWorldMatrix;
+ DrawSpecialCube(Vector3.zero, t.lossyScale);
+ }
+
+ private void DrawSpecialCube(Vector3 center, Vector3 size)
+ {
+ var color = Gizmos.color;
+ Gizmos.DrawWireCube(center, size);
+ Gizmos.color = new Color(color.r, color.g, color.b, 0.5f);
+ Gizmos.DrawCube(center, size);
+ }
+
+ private Color GetColorByGroupId(int group)
+ {
+ switch (group)
+ {
+ case 0: return Color.red;
+ case 1: return Color.blue;
+ case 2: return Color.green;
+ case 3: return Color.yellow;
+ case 4: return Color.magenta;
+ case 5: return Color.cyan;
+ case 6: return new Color(1f, 0.5f, 0f);
+ case 7: return new Color(0.4f, 0.01f, 0.5f);
+ case 8: return new Color(0.63f, 0.87f, 0f);
+ case 9: return new Color(0.98f, 0.67f, 0.91f);
+ case 10: return new Color(0.49f, 0.93f, 0.67f);
+ case 11: return new Color(0.11f, 0.55f, 0.8f);
+ default: return Color.white;
+ }
+ }
+
+ #endregion
+ }
+}