224 lines
6.6 KiB
C#
224 lines
6.6 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 NetworkVariable<bool> _isVisible = new NetworkVariable<bool>(
|
|
false,
|
|
NetworkVariableReadPermission.Everyone,
|
|
NetworkVariableWritePermission.Server
|
|
);
|
|
|
|
private bool _isCollected = false;
|
|
private Renderer[] _renderers;
|
|
private Collider[] _colliders;
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
base.OnNetworkSpawn();
|
|
|
|
// 렌더러와 콜라이더 캐시
|
|
_renderers = GetComponentsInChildren<Renderer>();
|
|
_colliders = GetComponentsInChildren<Collider>();
|
|
|
|
// 초기 가시성 적용
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 가시성 설정 (서버만 호출 가능)
|
|
/// </summary>
|
|
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<NetworkPlayerController>();
|
|
if (controller != null && controller.IsLocalPlayer)
|
|
{
|
|
var inventory = kvp.Value.GetComponent<PlayerResourceInventory>();
|
|
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;
|
|
}
|
|
}
|
|
} |