using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif [ExecuteAlways] public class CharacterHitboxAutoSetup : MonoBehaviour { [Header("References")] [SerializeField] private Animator animator; [SerializeField] private EnemyCombat enemyCombat; [Header("Hitbox Settings")] [SerializeField] private Vector3 handHitboxSize = new Vector3(0.35f, 0.35f, 0.35f); [SerializeField] private Vector3 footHitboxSize = new Vector3(0.45f, 0.35f, 0.45f); [SerializeField] private float punchDamage = 10f; [SerializeField] private float kickDamage = 15f; [Header("Hurtbox Settings")] [SerializeField] private Vector3 headHurtboxSize = new Vector3(0.35f, 0.35f, 0.35f); [SerializeField] private Vector3 bodyHurtboxSize = new Vector3(0.55f, 0.75f, 0.35f); [SerializeField] private Vector3 legHurtboxSize = new Vector3(0.35f, 0.6f, 0.35f); [Header("Optional")] [SerializeField] private GameObject bloodVFXPrefab; [ContextMenu("Auto Setup Hitboxes And Hurtboxes")] public void AutoSetup() { FindReferences(); if (animator == null) { Debug.LogError("Animator not found on " + gameObject.name); return; } if (!animator.isHuman) { Debug.LogError("Animator is not Humanoid. Set model Rig Type to Humanoid first: " + gameObject.name); return; } SetupHitboxes(); SetupHurtboxes(); #if UNITY_EDITOR EditorUtility.SetDirty(gameObject); if (enemyCombat != null) EditorUtility.SetDirty(enemyCombat); #endif Debug.Log("Hitboxes and hurtboxes setup completed for " + gameObject.name); } private void FindReferences() { if (animator == null) animator = GetComponentInChildren(); if (enemyCombat == null) enemyCombat = GetComponent(); if (enemyCombat == null) enemyCombat = gameObject.AddComponent(); } private void SetupHitboxes() { enemyCombat.rightHandPunchHitbox = CreateHitbox( "RightHandPunchHitbox", HumanBodyBones.RightHand, handHitboxSize, punchDamage ); enemyCombat.leftHandPunchHitbox = CreateHitbox( "LeftHandPunchHitbox", HumanBodyBones.LeftHand, handHitboxSize, punchDamage ); enemyCombat.rightFootKickHitbox = CreateHitbox( "RightFootKickHitbox", HumanBodyBones.RightFoot, footHitboxSize, kickDamage ); enemyCombat.leftFootKickHitbox = CreateHitbox( "LeftFootKickHitbox", HumanBodyBones.LeftFoot, footHitboxSize, kickDamage ); //enemyCombat.DisableAll(); } private GameObject CreateHitbox(string objectName, HumanBodyBones bone, Vector3 size, float damage) { Transform boneTransform = animator.GetBoneTransform(bone); if (boneTransform == null) { Debug.LogWarning("Missing bone: " + bone + " on " + gameObject.name); return null; } GameObject hitboxObject = GetOrCreateChild(boneTransform, objectName); BoxCollider boxCollider = hitboxObject.GetComponent(); if (boxCollider == null) boxCollider = hitboxObject.AddComponent(); boxCollider.isTrigger = true; boxCollider.size = size; boxCollider.center = Vector3.zero; Hitbox hitbox = hitboxObject.GetComponent(); if (hitbox == null) hitbox = hitboxObject.AddComponent(); hitbox.damage = damage; hitbox.bloodVFXPrefab = bloodVFXPrefab; int hitboxLayer = LayerMask.NameToLayer("Hitbox"); if (hitboxLayer != -1) hitboxObject.layer = hitboxLayer; hitboxObject.SetActive(false); return hitboxObject; } private void SetupHurtboxes() { CreateHurtbox("HeadHurtbox", HumanBodyBones.Head, headHurtboxSize, "Head"); CreateHurtbox("ChestHurtbox", HumanBodyBones.Chest, bodyHurtboxSize, "Body"); CreateHurtbox("HipsHurtbox", HumanBodyBones.Hips, bodyHurtboxSize, "Body"); CreateHurtbox("LeftUpperLegHurtbox", HumanBodyBones.LeftUpperLeg, legHurtboxSize, "Legs"); CreateHurtbox("RightUpperLegHurtbox", HumanBodyBones.RightUpperLeg, legHurtboxSize, "Legs"); } private GameObject CreateHurtbox(string objectName, HumanBodyBones bone, Vector3 size, string bodyPart) { Transform boneTransform = animator.GetBoneTransform(bone); if (boneTransform == null) { Debug.LogWarning("Missing bone: " + bone + " on " + gameObject.name); return null; } GameObject hurtboxObject = GetOrCreateChild(boneTransform, objectName); BoxCollider boxCollider = hurtboxObject.GetComponent(); if (boxCollider == null) boxCollider = hurtboxObject.AddComponent(); boxCollider.isTrigger = true; boxCollider.size = size; boxCollider.center = Vector3.zero; Hurtbox hurtbox = hurtboxObject.GetComponent(); if (hurtbox == null) hurtbox = hurtboxObject.AddComponent(); hurtbox.bodyPart = bodyPart; int hurtboxLayer = LayerMask.NameToLayer("Hurtbox"); if (hurtboxLayer != -1) hurtboxObject.layer = hurtboxLayer; hurtboxObject.SetActive(true); return hurtboxObject; } private GameObject GetOrCreateChild(Transform parent, string objectName) { Transform existing = parent.Find(objectName); if (existing != null) return existing.gameObject; GameObject newObject = new GameObject(objectName); newObject.transform.SetParent(parent); newObject.transform.localPosition = Vector3.zero; newObject.transform.localRotation = Quaternion.identity; newObject.transform.localScale = Vector3.one; return newObject; } }