CapersProject/Assets/02.Scripts/Item/Item.cs

224 lines
6.6 KiB
C#
Raw Normal View History

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]
2024-09-26 11:50:39 +00:00
public InteractionCanvas InteractionCanvas { get; private set; }
[field: Title("드랍 옵션")]
[field: SerializeField, Tooltip("키 입력을 통한 아이템 획득")]
public bool EnableInteraction { get; private set; } = true;
[field: SerializeField]
public float InteractionRadius { get; private set; } = 2f;
2024-09-24 10:35:49 +00:00
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;
2024-09-12 07:36:24 +00:00
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>();
2024-09-26 11:50:39 +00:00
InteractionCanvas = transform.GetComponentInChildren<InteractionCanvas>();
}
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();
}
2024-09-09 12:27:15 +00:00
public virtual void CancelInteraction() { }
public virtual bool CanInteraction() => true;
public void ShowInteractionUi()
{
2024-09-24 10:35:49 +00:00
InteractionMessage = $"{ItemData.Name} 줍기";
EventManager.OnShowInteractionUi?.Invoke(InteractionMessage);
}
public void HideInteractionUi()
{
2024-09-24 10:35:49 +00:00
EventManager.OnHideInteractionUi?.Invoke();
}
private void DestroySelf() => Destroy(gameObject);
}
}