200 lines
7.1 KiB
C#
200 lines
7.1 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.XR;
|
|
|
|
/// <summary>
|
|
/// VR 플레이어의 몸, 손, 컨트롤러 Collider에 붙여서
|
|
/// "이 Collider는 인벤토리 아이템을 획득할 수 있다"고 표시하는 컴포넌트입니다.
|
|
/// 기능: 획득 허용/차단, InventoryManager Override, 컨트롤러 햅틱, 빠른 아이템 사용 메서드.
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
public class PlayerInventoryCollector : MonoBehaviour
|
|
{
|
|
[Header("Collection")]
|
|
[SerializeField] private bool canCollectItems = true;
|
|
[SerializeField] private InventoryManager inventoryManagerOverride;
|
|
[Tooltip("확인창이 필요한 아이템을 빠른 사용으로 눌렀을 때 InventoryUI의 확인창을 사용합니다.")]
|
|
[SerializeField] private bool respectInventoryUseConfirmation = true;
|
|
[SerializeField] private InventoryUI inventoryUIForConfirmedUses;
|
|
|
|
[Header("Haptic")]
|
|
[SerializeField] private bool enableHaptic = true;
|
|
[SerializeField] private XRNode hapticNode = XRNode.RightHand;
|
|
[Range(0f, 1f)] [SerializeField] private float defaultHapticAmplitude = 0.35f;
|
|
[SerializeField] private float defaultHapticDuration = 0.08f;
|
|
|
|
[Header("Quick Use - Compass")]
|
|
[SerializeField] private bool consumeCompassOnQuickUse = false;
|
|
[SerializeField] private string compassMissingMessage = "낡은 나침반이 필요합니다.";
|
|
[SerializeField] private string compassUsedMessage = "나침반이 방향을 가리킵니다.";
|
|
public UnityEvent onCompassUsed;
|
|
public UnityEvent onCompassMissing;
|
|
|
|
[Header("Quick Use - Fish")]
|
|
[SerializeField] private int fishUseAmount = 1;
|
|
[SerializeField] private string fishMissingMessage = "생선이 부족합니다.";
|
|
[SerializeField] private string fishUsedMessage = "생선을 사용했습니다.";
|
|
public UnityEvent onFishUsed;
|
|
public UnityEvent onFishMissing;
|
|
|
|
[Header("Quick Use - Trash")]
|
|
[SerializeField] private int trashUseAmount = 1;
|
|
[SerializeField] private string trashMissingMessage = "쓰레기가 부족합니다.";
|
|
[SerializeField] private string trashUsedMessage = "쓰레기를 사용했습니다.";
|
|
public UnityEvent onTrashUsed;
|
|
public UnityEvent onTrashMissing;
|
|
|
|
[Header("Quick Use - Bottle")]
|
|
[SerializeField] private bool consumeBottleOnQuickUse = false;
|
|
[SerializeField] private string bottleMissingMessage = "마법병이 필요합니다.";
|
|
[SerializeField] private string bottleUsedMessage = "마법병을 사용했습니다.";
|
|
public UnityEvent onBottleUsed;
|
|
public UnityEvent onBottleMissing;
|
|
|
|
[Header("Quick Use - Memory Piece")]
|
|
[SerializeField] private string memoryPieceMissingMessage = "기억의 조각이 없습니다.";
|
|
[SerializeField] private string memoryPieceUsedMessage = "기억의 조각을 확인했습니다.";
|
|
public UnityEvent onMemoryPieceUsed;
|
|
public UnityEvent onMemoryPieceMissing;
|
|
|
|
public bool CanCollectItems => canCollectItems;
|
|
public InventoryManager InventoryManagerOverride => inventoryManagerOverride;
|
|
|
|
public void SetCanCollectItems(bool canCollect)
|
|
{
|
|
canCollectItems = canCollect;
|
|
}
|
|
|
|
public void SetInventoryManagerOverride(InventoryManager manager)
|
|
{
|
|
inventoryManagerOverride = manager;
|
|
}
|
|
|
|
public void PlayDefaultHaptic()
|
|
{
|
|
PlayHaptic(defaultHapticAmplitude, defaultHapticDuration);
|
|
}
|
|
|
|
public void PlayHaptic(float amplitude, float duration)
|
|
{
|
|
if (!enableHaptic)
|
|
return;
|
|
|
|
InputDevice device = InputDevices.GetDeviceAtXRNode(hapticNode);
|
|
if (!device.isValid)
|
|
return;
|
|
|
|
HapticCapabilities capabilities;
|
|
if (device.TryGetHapticCapabilities(out capabilities) && capabilities.supportsImpulse)
|
|
device.SendHapticImpulse(0, Mathf.Clamp01(amplitude), Mathf.Max(0f, duration));
|
|
}
|
|
|
|
public void UseCompass()
|
|
{
|
|
InventoryManager manager = ResolveManager();
|
|
if (manager == null)
|
|
return;
|
|
|
|
bool result = manager.TryUseItem(InventoryItemType.OldCompass, 1, consumeCompassOnQuickUse, false, true);
|
|
if (result)
|
|
{
|
|
manager.RequestMessage(compassUsedMessage);
|
|
PlayDefaultHaptic();
|
|
onCompassUsed?.Invoke();
|
|
}
|
|
else
|
|
{
|
|
manager.RequestMessage(compassMissingMessage);
|
|
onCompassMissing?.Invoke();
|
|
}
|
|
}
|
|
|
|
public void UseFish()
|
|
{
|
|
TryUseQuickItem(InventoryItemType.Fish, fishUseAmount, true, fishUsedMessage, fishMissingMessage, onFishUsed, onFishMissing);
|
|
}
|
|
|
|
public void UseTrash()
|
|
{
|
|
TryUseQuickItem(InventoryItemType.Trash, trashUseAmount, true, trashUsedMessage, trashMissingMessage, onTrashUsed, onTrashMissing);
|
|
}
|
|
|
|
public void UseBottle()
|
|
{
|
|
TryUseQuickItem(InventoryItemType.Bottle, 1, consumeBottleOnQuickUse, bottleUsedMessage, bottleMissingMessage, onBottleUsed, onBottleMissing);
|
|
}
|
|
|
|
public void UseMemoryPiece()
|
|
{
|
|
TryUseQuickItem(InventoryItemType.MemoryPiece, 1, false, memoryPieceUsedMessage, memoryPieceMissingMessage, onMemoryPieceUsed, onMemoryPieceMissing);
|
|
}
|
|
|
|
public bool TryUseQuickItem(InventoryItemType itemType, int amount, bool consume, string successMessage, string missingMessage, UnityEvent onSuccess, UnityEvent onFail)
|
|
{
|
|
InventoryManager manager = ResolveManager();
|
|
if (manager == null)
|
|
return false;
|
|
|
|
amount = Mathf.Max(1, amount);
|
|
|
|
if (respectInventoryUseConfirmation && manager.RequiresUseConfirmation(itemType))
|
|
{
|
|
InventoryUI ui = ResolveInventoryUI();
|
|
if (ui != null)
|
|
{
|
|
ui.RequestUseItem(itemType, amount);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool result = manager.TryUseItem(itemType, amount, consume, false, true);
|
|
|
|
if (result)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(successMessage))
|
|
manager.RequestMessage(successMessage);
|
|
|
|
PlayDefaultHaptic();
|
|
onSuccess?.Invoke();
|
|
return true;
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(missingMessage))
|
|
manager.RequestMessage(missingMessage);
|
|
else
|
|
manager.RequestMessage(manager.GetInsufficientMessage(itemType, amount));
|
|
|
|
onFail?.Invoke();
|
|
return false;
|
|
}
|
|
|
|
private InventoryUI ResolveInventoryUI()
|
|
{
|
|
if (inventoryUIForConfirmedUses != null)
|
|
return inventoryUIForConfirmedUses;
|
|
|
|
inventoryUIForConfirmedUses = FindFirstObjectByType<InventoryUI>();
|
|
return inventoryUIForConfirmedUses;
|
|
}
|
|
|
|
private InventoryManager ResolveManager()
|
|
{
|
|
if (inventoryManagerOverride != null)
|
|
return inventoryManagerOverride;
|
|
|
|
if (InventoryManager.Instance != null)
|
|
return InventoryManager.Instance;
|
|
|
|
return FindFirstObjectByType<InventoryManager>();
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
private void OnValidate()
|
|
{
|
|
fishUseAmount = Mathf.Max(1, fishUseAmount);
|
|
trashUseAmount = Mathf.Max(1, trashUseAmount);
|
|
defaultHapticDuration = Mathf.Max(0f, defaultHapticDuration);
|
|
}
|
|
#endif
|
|
}
|