using System.Collections; using BlueWater.Audios; using BlueWater.Interfaces; using BlueWater.Maps; using BlueWater.Uis; using BlueWater.Utility; using Sirenix.OdinInspector; using UnityEngine; namespace BlueWater.Items { public class Item : MonoBehaviour, IPlayerInteraction { [field: Title("컴포넌트")] public Transform CenterTransform { get; private set; } [SerializeField] protected Rigidbody Rigidbody; [SerializeField] protected Collider Collider; [SerializeField] protected Transform VisualLook; [SerializeField] protected SpriteRenderer SpriteRenderer; [field: SerializeField] public Canvas InteractionCanvas { get; private set; } public Transform InteractionUi { get; private set; } [field: Title("드랍 옵션")] [field: SerializeField, Tooltip("키 입력을 통한 아이템 획득")] public bool EnableInteraction { get; private set; } = true; [field: SerializeField] public float InteractionRadius { get; private set; } = 2f; public string InteractionMessage { get; private set; } [SerializeField] protected bool UseAutoDestroy = true; [SerializeField, ShowIf("@UseAutoDestroy")] protected float AutoDestroyTime = 30f; [SerializeField, ShowIf("@!EnableInteraction")] protected bool DrawGizmos = true; [SerializeField, ShowIf("@!EnableInteraction")] protected float Radius = 5f; [SerializeField, ShowIf("@!EnableInteraction")] protected float AcquisitionTime = 1f; [SerializeField, ShowIf("@!EnableInteraction")] protected float DropWaitTime = 0.7f; [SerializeField] protected string AcquiredSfxName = "GetItem"; [Title("아이템 데이터")] [SerializeField] protected ItemData ItemData; protected ItemSlot ItemSlot; protected Collider TargetCollider; protected Coroutine RootCoroutineInstance; protected readonly WaitForSeconds LootCoroutineTime = new(0.5f); private bool _isQuitting; private void OnDrawGizmosSelected() { if (!DrawGizmos) return; Gizmos.DrawWireSphere(transform.position, Radius); } private void Awake() { InitializeComponents(); } private void Start() { MapManager.Instance.OnHardResetAllMap += DestroySelf; if (UseAutoDestroy) { Destroy(gameObject, AutoDestroyTime); } if (EnableInteraction) { GameManager.Instance.CurrentCombatPlayer.CombatInput.RegisterPlayerInteraction(this); } else { Utils.StartUniqueCoroutine(this, ref RootCoroutineInstance, LootCoroutine()); } } private void OnApplicationQuit() { _isQuitting = true; } private void OnDestroy() { if (_isQuitting) return; MapManager.Instance.OnHardResetAllMap -= DestroySelf; if (EnableInteraction) { GameManager.Instance.CurrentCombatPlayer.CombatInput.UnregisterPlayerInteraction(this); } } public void Initialize(ItemSlot itemSlot) { ItemSlot = itemSlot; ItemData = ItemManager.Instance.ItemDataSo.GetDataByIdx(ItemSlot.Idx); SpriteRenderer.sprite = ItemData.Sprite; } [Button("컴포넌트 초기화")] private void InitializeComponents() { if (!CenterTransform) { CenterTransform = transform; } Rigidbody = GetComponent(); Collider = GetComponent(); VisualLook = transform.Find("VisualLook"); SpriteRenderer = VisualLook.GetComponent(); InteractionCanvas = transform.Find("InteractionCanvas").GetComponent(); InteractionCanvas.GetComponent().worldCamera = CombatCameraManager.Instance.UiCamera; InteractionUi = transform.Find("InteractionUi"); } protected virtual void OnAcquired() { Destroy(gameObject); AudioManager.Instance.PlaySfx(AcquiredSfxName); DataManager.Instance.Inventory.AddItem(ItemSlot); CombatUiManager.Instance.ItemLootUi.ShowLootInfoUi(ItemData, ItemSlot.Quantity); } private IEnumerator LootCoroutine() { yield return new WaitForSeconds(DropWaitTime); while (true) { TargetCollider = GameManager.Instance.CurrentCombatPlayer.CharacterCollider; if (TargetCollider == null) { yield return LootCoroutineTime; continue; } var targetDistance = Vector3.Distance(TargetCollider.transform.position, transform.position); if (targetDistance <= Radius) break; yield return LootCoroutineTime; } if (Rigidbody) { Rigidbody.isKinematic = true; Rigidbody.useGravity = false; } if (Collider) { Collider.enabled = false; } var startPosition = transform.position; var elapsedTime = 0f; while (elapsedTime < AcquisitionTime) { if (TargetCollider == null) { yield break; } elapsedTime += Time.deltaTime; var t = elapsedTime / AcquisitionTime; t = Mathf.SmoothStep(0f, 1f, t); transform.position = Vector3.Lerp(startPosition, TargetCollider.bounds.center, t); yield return null; } OnAcquired(); } public void AddForce(Vector3 force, ForceMode forceMode) => Rigidbody.AddForce(force, forceMode); public void Interaction() { OnAcquired(); } public virtual void CancelInteraction() { } public virtual bool CanInteraction() => true; public void ShowInteractionUi() { InteractionMessage = $"{ItemData.Name} 줍기"; EventManager.OnShowInteractionUi?.Invoke(InteractionMessage); // if (!InteractionCanvas) return; // // InteractionCanvas.gameObject.SetActive(true); } public void HideInteractionUi() { EventManager.OnHideInteractionUi?.Invoke(); // if (!InteractionCanvas) return; // // InteractionCanvas.gameObject.SetActive(false); } private void DestroySelf() => Destroy(gameObject); } }