Files
Northbound/Assets/Scripts/ResourcePickup.cs
2026-01-27 17:05:35 +09:00

156 lines
5.0 KiB
C#

using Unity.Netcode;
using UnityEngine;
namespace Northbound
{
/// <summary>
/// 일회용 자원 아이템 - 상호작용 시 자원 획득 후 사라짐
/// </summary>
public class ResourcePickup : NetworkBehaviour, IInteractable
{
[Header("Resource Settings")]
public int resourceAmount = 50; // 획득할 자원량
public string resourceName = "보급품";
[Header("Animation")]
public string interactionAnimationTrigger = "PickUp"; // 플레이어 애니메이션 트리거
[Header("Equipment")]
public InteractionEquipmentData equipmentData = new InteractionEquipmentData
{
socketName = "",
attachOnStart = false,
detachOnEnd = false
};
[Header("Visual")]
public GameObject pickupEffectPrefab;
public Transform effectSpawnPoint;
private bool _isCollected = false;
public bool CanInteract(ulong playerId)
{
// 이미 수집됨
if (_isCollected)
return false;
// 플레이어 인벤토리 확인
if (NetworkManager.Singleton != null &&
NetworkManager.Singleton.ConnectedClients.TryGetValue(playerId, out var client))
{
if (client.PlayerObject != null)
{
var playerInventory = client.PlayerObject.GetComponent<PlayerResourceInventory>();
if (playerInventory != null)
{
// 플레이어가 받을 수 있는 공간이 없으면 상호작용 불가
if (playerInventory.GetAvailableSpace() <= 0)
return false;
}
}
}
return true;
}
public void Interact(ulong playerId)
{
if (!CanInteract(playerId))
return;
CollectResourceServerRpc(playerId);
}
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
private void CollectResourceServerRpc(ulong playerId)
{
if (!CanInteract(playerId))
return;
// 중복 수집 방지
if (_isCollected)
return;
_isCollected = true;
// 플레이어의 인벤토리 확인
var playerObject = NetworkManager.Singleton.ConnectedClients[playerId].PlayerObject;
if (playerObject == null)
return;
var playerInventory = playerObject.GetComponent<PlayerResourceInventory>();
if (playerInventory == null)
{
Debug.LogWarning($"플레이어 {playerId}에게 PlayerResourceInventory 컴포넌트가 없습니다.");
return;
}
// 플레이어가 받을 수 있는 최대량 계산
int playerAvailableSpace = playerInventory.GetAvailableSpace();
// 실제 지급할 양 계산
int collectedAmount = Mathf.Min(resourceAmount, playerAvailableSpace);
if (collectedAmount <= 0)
{
Debug.Log($"플레이어 {playerId}의 인벤토리가 가득 찼습니다.");
_isCollected = false; // 수집 실패 시 다시 시도 가능하도록
return;
}
// 플레이어에게 자원 추가
playerInventory.AddResourceServerRpc(collectedAmount);
Debug.Log($"플레이어 {playerId}가 {collectedAmount} {resourceName}을(를) 획득했습니다.");
// 이펙트 표시 및 오브젝트 제거
ShowPickupEffectClientRpc();
// 짧은 딜레이 후 제거 (이펙트를 위해)
Invoke(nameof(DestroyPickup), 0.1f);
}
[Rpc(SendTo.ClientsAndHost)]
private void ShowPickupEffectClientRpc()
{
if (pickupEffectPrefab != null)
{
Transform spawnPoint = effectSpawnPoint != null ? effectSpawnPoint : transform;
GameObject effect = Instantiate(pickupEffectPrefab, spawnPoint.position, spawnPoint.rotation);
Destroy(effect, 2f);
}
// 오브젝트를 즉시 비활성화하여 재상호작용 방지
gameObject.SetActive(false);
}
private void DestroyPickup()
{
if (IsServer && NetworkObject != null)
{
NetworkObject.Despawn(true);
}
}
public string GetInteractionPrompt()
{
return $"[E] {resourceName} 획득 (+{resourceAmount})";
}
public string GetInteractionAnimation()
{
return interactionAnimationTrigger;
}
public InteractionEquipmentData GetEquipmentData()
{
return equipmentData;
}
public Transform GetTransform()
{
return transform;
}
}
}