using Unity.Netcode;
using UnityEngine;
namespace Northbound
{
///
/// 일회용 자원 아이템 - 상호작용 시 자원 획득 후 사라짐
///
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 NetworkVariable _isVisible = new NetworkVariable(
false,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server
);
private bool _isCollected = false;
private Renderer[] _renderers;
private Collider[] _colliders;
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
// 렌더러와 콜라이더 캐시
_renderers = GetComponentsInChildren();
_colliders = GetComponentsInChildren();
// 초기 가시성 적용
UpdateVisibility(_isVisible.Value);
// 가시성 변경 이벤트 구독
_isVisible.OnValueChanged += OnVisibilityChanged;
}
public override void OnNetworkDespawn()
{
_isVisible.OnValueChanged -= OnVisibilityChanged;
base.OnNetworkDespawn();
}
private void OnVisibilityChanged(bool previousValue, bool newValue)
{
UpdateVisibility(newValue);
}
private void UpdateVisibility(bool visible)
{
if (_renderers != null)
{
foreach (var renderer in _renderers)
{
if (renderer != null)
renderer.enabled = visible;
}
}
if (_colliders != null)
{
foreach (var collider in _colliders)
{
if (collider != null)
collider.enabled = visible;
}
}
}
///
/// 가시성 설정 (서버만 호출 가능)
///
public void SetVisible(bool visible)
{
if (IsServer)
{
_isVisible.Value = visible;
}
}
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)
{
_isCollected = false;
return;
}
resourceManager.AddResource(playerId, collectedAmount);
UpdatePlayerResourcesClientRpc(playerId);
ShowPickupEffectClientRpc();
Invoke(nameof(DestroyPickup), 0.1f);
}
[Rpc(SendTo.ClientsAndHost)]
private void UpdatePlayerResourcesClientRpc(ulong playerId)
{
// 해당 플레이어만 업데이트
if (NetworkManager.Singleton.LocalClientId != playerId)
return;
// 로컬 플레이어의 PlayerResourceInventory 찾아서 업데이트 요청
var spawnedObjects = NetworkManager.Singleton.SpawnManager.SpawnedObjects;
foreach (var kvp in spawnedObjects)
{
var controller = kvp.Value.GetComponent();
if (controller != null && controller.IsLocalPlayer)
{
var inventory = kvp.Value.GetComponent();
if (inventory != null)
{
inventory.RequestResourceUpdateServerRpc(playerId);
return;
}
}
}
}
[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} Get (+{resourceAmount})";
}
public string GetInteractionAnimation()
{
return interactionAnimationTrigger;
}
public EquipmentData GetEquipmentData()
{
return equipmentData;
}
public Transform GetTransform()
{
return transform;
}
}
}