Files
Northbound/Assets/Scripts/ResourcePickup.cs
dal4segno 10b496dfae 네트워크 멀티플레이 환경 문제 수정
관련 문제가 다시 발생하면 이 커밋으로 돌아올 것
2026-02-02 04:24:14 +09:00

150 lines
4.5 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 EquipmentData equipmentData = new EquipmentData
{
socketName = "",
equipmentPrefab = null,
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;
var resourceManager = ServerResourceManager.Instance;
if (resourceManager != null)
{
if (resourceManager.GetAvailableSpace(playerId) <= 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 resourceManager = ServerResourceManager.Instance;
if (resourceManager == null)
{
Debug.LogWarning("ServerResourceManager 인스턴스를 찾을 수 없습니다.");
_isCollected = false;
return;
}
int playerAvailableSpace = resourceManager.GetAvailableSpace(playerId);
int collectedAmount = Mathf.Min(resourceAmount, playerAvailableSpace);
if (collectedAmount <= 0)
{
Debug.Log($"플레이어 {playerId}의 인벤토리가 가득 찼습니다.");
_isCollected = false;
return;
}
resourceManager.AddResource(playerId, collectedAmount);
UpdatePlayerResourcesClientRpc(playerId);
Debug.Log($"플레이어 {playerId}가 {collectedAmount} {resourceName}을(를) 획득했습니다.");
ShowPickupEffectClientRpc();
Invoke(nameof(DestroyPickup), 0.1f);
}
[Rpc(SendTo.ClientsAndHost)]
private void UpdatePlayerResourcesClientRpc(ulong playerId)
{
var playerObject = NetworkManager.Singleton.ConnectedClients[playerId].PlayerObject;
if (playerObject != null)
{
var playerInventory = playerObject.GetComponent<PlayerResourceInventory>();
if (playerInventory != null)
{
playerInventory.RequestResourceUpdateServerRpc();
}
}
}
[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 EquipmentData GetEquipmentData()
{
return equipmentData;
}
public Transform GetTransform()
{
return transform;
}
}
}