2026.06.24
This commit is contained in:
199
Assets/My project/Inventory/Scripts/PlayerInventoryCollector.cs
Normal file
199
Assets/My project/Inventory/Scripts/PlayerInventoryCollector.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user