using UnityEngine; /// /// 바닥에 떨어진 화살 아이템 (발사체로도 사용 가능) /// 모드 전환: 아이템 모드 ↔ 발사 모드 /// public class ArrowItem : MonoBehaviour { [Header("--- 화살 정보 ---")] [SerializeField] private string arrowName = "기본 화살"; [SerializeField] private float damage = 15f; [SerializeField] private float speed = 20f; [SerializeField] private float range = 15f; [Header("--- UI 표시 (아이템 모드) ---")] [SerializeField] private GameObject pickupUI; [SerializeField] private float uiDisplayRange = 3f; [Header("--- 비주얼 ---")] [SerializeField] private GameObject visualModel; // 화살 모델 private Transform playerTransform; private Rigidbody rb; private Collider col; // 모드 구분 private bool isItemMode = true; // true: 아이템 모드, false: 발사 모드 private Vector3 startPos; private bool isFired = false; private void Awake() { rb = GetComponent(); col = GetComponent(); } private void Start() { if (isItemMode) { SetupAsItem(); } } private void Update() { if (isItemMode) { UpdateItemMode(); } else { UpdateProjectileMode(); } } #region 아이템 모드 private void SetupAsItem() { // 플레이어 찾기 GameObject player = GameObject.FindGameObjectWithTag("Player"); if (player != null) { playerTransform = player.transform; } // UI 숨기기 if (pickupUI != null) { pickupUI.SetActive(false); } // 물리 설정 (바닥에 떨어진 아이템) if (rb != null) { rb.useGravity = true; rb.isKinematic = false; } if (col != null) { col.isTrigger = true; } } private void UpdateItemMode() { if (playerTransform == null || pickupUI == null) return; // 플레이어와의 거리 체크 (UI 표시용) float distance = Vector3.Distance(transform.position, playerTransform.position); bool isNear = distance <= uiDisplayRange; pickupUI.SetActive(isNear); } /// /// PlayerInteraction에서 호출 /// public void Pickup(PlayerAttack playerAttack) { if (playerAttack == null) return; // 자기 자신을 복제해서 발사용 프리팹으로 제공 GameObject arrowPrefab = gameObject; playerAttack.SwapArrow(arrowPrefab); Debug.Log($"화살이 [{arrowName}](으)로 교체되었습니다!"); // 아이템 제거 Destroy(gameObject); } #endregion #region 발사 모드 /// /// PlayerAttack에서 호출 (발사 초기화) /// public void Initialize(float dmg, float arrowSpeed, float maxRange) { Debug.Log($"🏹 화살 발사! 방향: {transform.forward}, 속도: {arrowSpeed}"); // 발사 모드로 전환 isItemMode = false; isFired = true; // 스탯 설정 this.damage = dmg; this.speed = arrowSpeed; this.range = maxRange; this.startPos = transform.position; // UI 숨기기 if (pickupUI != null) { pickupUI.SetActive(false); } // 물리 설정 (발사체) if (rb != null) { rb.useGravity = false; rb.isKinematic = false; // ✅ [중요] transform.forward 방향으로 발사 // 화살이 Z축(파란 화살표) 방향을 앞으로 향하고 있어야 함! Vector3 shootDirection = transform.forward; rb.velocity = shootDirection * speed; Debug.Log($"📍 발사 방향: {shootDirection}, 속도 벡터: {rb.velocity}"); } if (col != null) { col.isTrigger = true; } // 5초 후 자동 삭제 Destroy(gameObject, 5f); } private void UpdateProjectileMode() { if (!isFired) return; // 최대 사거리 체크 if (Vector3.Distance(startPos, transform.position) >= range) { Destroy(gameObject); } } private void OnTriggerEnter(Collider other) { // 아이템 모드에서는 충돌 무시 if (isItemMode) return; // 발사 모드: 적 또는 벽 충돌 if (other.CompareTag("Enemy")) { var monster = other.GetComponent(); if (monster != null) { monster.TakeDamage(damage); } Destroy(gameObject); } else if (other.CompareTag("Wall") || other.CompareTag("Ground")) { Destroy(gameObject); } } #endregion #region 외부 설정용 /// /// 몬스터 드롭 시 화살 정보 설정 /// public void SetArrowData(string name, float dmg, float spd, float rng) { arrowName = name; damage = dmg; speed = spd; range = rng; } #endregion }