using UnityEngine; using UnityEngine.AI; using System.Collections; using System.Collections.Generic; // ✅ 리스트 사용을 위해 필수 추가 public class MeleeMonster : MonsterClass { [Header("=== 근접 공격 설정 ===")] //[SerializeField] private MonsterWeapon myWeapon; // ✅ 주석 해제됨 (이제 무기 연결 가능!) [SerializeField] private float attackRange = 2f; [SerializeField] private float attackDelay = 1.5f; // 🎁 [수정] 단일 아이템 -> 리스트로 변경 [Header("=== 드랍 아이템 설정 ===")] [Tooltip("드랍 가능한 아이템들을 여기에 여러 개 등록하세요. (랜덤 1개 드랍)")] [SerializeField] private List dropItemPrefabs; [Tooltip("아이템이 나올 확률 (0 ~ 100%)")] [Range(0, 100)][SerializeField] private float dropChance = 30f; // 기본 30% private float lastAttackTime; [Header("공격 / 이동 애니메이션")] [SerializeField] private string[] attackAnimations = { "Monster_Attack_1" }; [SerializeField] private string Monster_Walk = "Monster_Walk"; [Header("AI 상세 설정")] [SerializeField] private float stopBuffer = 0.3f; [SerializeField] private float patrolRadius = 5f; [SerializeField] private float patrolInterval = 2f; private float nextPatrolTime; private float repathInterval = 0.3f; private float nextRepathTime; private int attackIndex; private bool isPlayerInZone; protected override void Init() { if (agent != null) agent.stoppingDistance = attackRange - 0.4f; if (animator != null) animator.applyRootMotion = false; } protected override void OnResetStats() { if (myWeapon != null) { myWeapon.SetDamage(attackDamage); } } protected override void ExecuteAILogic() { if (isHit || isAttacking || isResting) return; float distance = Vector3.Distance(transform.position, playerTransform.position); if (isPlayerInZone || distance <= attackRange * 2f) HandlePlayerTarget(); else Patrol(); UpdateMovementAnimation(); } void HandlePlayerTarget() { float distance = Vector3.Distance(transform.position, playerTransform.position); if (distance <= attackRange - stopBuffer) TryAttack(); else if (Time.time >= nextRepathTime) { if (agent.isOnNavMesh) agent.SetDestination(playerTransform.position); nextRepathTime = Time.time + repathInterval; } } void TryAttack() { if (Time.time < lastAttackTime + attackDelay) return; lastAttackTime = Time.time; string attackName = attackAnimations[attackIndex]; attackIndex = (attackIndex + 1) % attackAnimations.Length; isAttacking = true; if (agent.isOnNavMesh) { agent.isStopped = true; agent.velocity = Vector3.zero; } animator.Play(attackName, 0, 0f); } void UpdateMovementAnimation() { if (isAttacking || isHit || isResting) return; if (agent.velocity.magnitude < 0.1f) animator.Play(Monster_Idle); else animator.Play(Monster_Walk); } void Patrol() { if (Time.time < nextPatrolTime) return; Vector3 randomPoint = transform.position + new Vector3( Random.Range(-patrolRadius, patrolRadius), 0, Random.Range(-patrolRadius, patrolRadius) ); if (NavMesh.SamplePosition(randomPoint, out NavMeshHit hit, 3f, NavMesh.AllAreas)) if (agent.isOnNavMesh) agent.SetDestination(hit.position); nextPatrolTime = Time.time + patrolInterval; } public override void OnAttackStart() { isAttacking = true; isResting = false; if (myWeapon != null) myWeapon.EnableHitBox(); } public override void OnAttackEnd() { if (myWeapon != null) myWeapon.DisableHitBox(); isAttacking = false; if (!isDead && !isHit) StartCoroutine(RestAfterAttack()); } protected override IEnumerator RestAfterAttack() { isResting = true; yield return new WaitForSeconds(attackRestDuration); isResting = false; } protected override void OnStartHit() { if (myWeapon != null) myWeapon.DisableHitBox(); } // 🎲 [핵심 수정] 리스트에서 랜덤 뽑기 + 확률 체크 protected override void OnDie() { if (myWeapon != null) myWeapon.DisableHitBox(); // 1. 리스트에 아이템이 하나라도 있는지 확인 if (dropItemPrefabs != null && dropItemPrefabs.Count > 0) { // 2. 확률 체크 (0 ~ 100) float randomValue = Random.Range(0f, 100f); if (randomValue <= dropChance) // 당첨! { // 3. 리스트에서 랜덤하게 하나 뽑기 (0번 ~ 마지막 번호 중 하나) int randomIndex = Random.Range(0, dropItemPrefabs.Count); GameObject selectedItem = dropItemPrefabs[randomIndex]; if (selectedItem != null) { Instantiate(selectedItem, transform.position + Vector3.up * 0.5f, Quaternion.identity); // Debug.Log($"🎉 아이템 드랍! ({selectedItem.name})"); } } } } private void OnTriggerEnter(Collider other) { if (other.CompareTag("Player")) isPlayerInZone = true; } private void OnTriggerExit(Collider other) { if (other.CompareTag("Player")) isPlayerInZone = false; } }