using System; using System.Collections.Generic; using UnityEngine; namespace Code.OfficeGame.BattleMode.HitBoxes { // TODO Добавить меотды отключения,чтобы не получать урон во время стаггера public class EntityHitBoxes : MonoBehaviour { [SerializeField] private Dictionary bodyParts; private LayerMask _hitBoxLayerMask; private readonly Collider[] _hitResults = new Collider[8]; private readonly HashSet _alreadyHitTargets = new(); private void Awake() { foreach (var part in bodyParts.Values) { part.enabled = false; } _hitBoxLayerMask = LayerMask.GetMask("HitBox"); } public void CheckHitsForCurrentFrame(Action onNewTargetHit, HitBoxPartType hitBoxPartType) { BoxCollider box = bodyParts[hitBoxPartType]; Transform boxTransform = box.transform; // Вычисляем точный мировой центр и размер коллайдера на кости в текущем кадре анимации Vector3 worldCenter = boxTransform.TransformPoint(box.center); Vector3 worldHalfExtents = Vector3.Scale(box.size * 0.5f, boxTransform.lossyScale); int hitsCount = Physics.OverlapBoxNonAlloc( worldCenter, worldHalfExtents, _hitResults, boxTransform.rotation, _hitBoxLayerMask, QueryTriggerInteraction.Collide); for (int i = 0; i < hitsCount; i++) { Collider hitCol = _hitResults[i]; // Игнорируем самого себя if (hitCol.transform.root == transform.root) continue; // Если за этот взмах мы ещё не били этого врага — засчитываем попадание! if (_alreadyHitTargets.Add(hitCol.gameObject)) { onNewTargetHit?.Invoke(hitCol); } } } } public enum HitBoxPartType { Head, Chest, LArm, LElbow, LWrist, LLeg, LKnee, LAnkle, RArm, RElbow, RWrist, RLeg, RKnee, RAnkle } }