From a9cef4bb0b902e3ec2d3b5510e3de4e885f2be90 Mon Sep 17 00:00:00 2001 From: SmallFox <2806143047@qq.com> Date: Sun, 10 May 2026 11:16:18 +0800 Subject: feat:合并伤害体积 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scripts/DamageVolumeSystem/DamageGenerator.cs | 159 +++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 Assets/Scripts/DamageVolumeSystem/DamageGenerator.cs (limited to 'Assets/Scripts/DamageVolumeSystem/DamageGenerator.cs') 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 _scannedHosts = new(); + + // 速度缩放 + private float _speedScale; + + // 上一帧的位置 + private Vector3 _lastPosition; + + private void Start() + { + _collider = GetComponent(); + } + + 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(); + if (damageHost != null && _scannedHosts.Add(damageHost)) + { + // 碰撞时立刻产生伤害 + if (emitOnCollide) + Emit(); + } + } + + private void OnTriggerExit(Collider other) + { + var damageHost = other.GetComponent(); + 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 + } +} -- cgit