234 lines
7.1 KiB
C#
234 lines
7.1 KiB
C#
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<Rigidbody>();
|
|
Collider = GetComponent<Collider>();
|
|
VisualLook = transform.Find("VisualLook");
|
|
SpriteRenderer = VisualLook.GetComponent<SpriteRenderer>();
|
|
InteractionCanvas = transform.Find("InteractionCanvas").GetComponent<Canvas>();
|
|
InteractionCanvas.GetComponent<Canvas>().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);
|
|
}
|
|
} |