190 lines
6.2 KiB
C#
190 lines
6.2 KiB
C#
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
namespace Northbound
|
|
{
|
|
/// <summary>
|
|
/// 상호작용 대상 - 자원 채집
|
|
/// </summary>
|
|
public class Resource : NetworkBehaviour, IInteractable
|
|
{
|
|
[Header("Resource Settings")]
|
|
public int maxResources = 100;
|
|
public int resourcesPerGathering = 10;
|
|
public float gatheringCooldown = 2f;
|
|
public string resourceName = "광석";
|
|
|
|
[Header("Resource Recharge")]
|
|
public float rechargeInterval = 5f; // 충전 주기 (초)
|
|
public int rechargeAmount = 10; // 주기당 충전량
|
|
|
|
[Header("Animation")]
|
|
public string interactionAnimationTrigger = "Mining"; // 플레이어 애니메이션 트리거
|
|
|
|
[Header("Equipment")]
|
|
public InteractionEquipmentData equipmentData = new InteractionEquipmentData
|
|
{
|
|
socketName = "RightHand",
|
|
attachOnStart = true,
|
|
detachOnEnd = true
|
|
};
|
|
|
|
[Header("Visual")]
|
|
public GameObject gatheringEffectPrefab;
|
|
public Transform effectSpawnPoint;
|
|
|
|
private NetworkVariable<int> _currentResources = new NetworkVariable<int>(
|
|
0,
|
|
NetworkVariableReadPermission.Everyone,
|
|
NetworkVariableWritePermission.Server
|
|
);
|
|
|
|
private float _lastGatheringTime;
|
|
private float _lastRechargeTime;
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
if (IsServer)
|
|
{
|
|
_currentResources.Value = 0;
|
|
_lastRechargeTime = Time.time;
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!IsServer)
|
|
return;
|
|
|
|
// 자원 충전 로직
|
|
if (Time.time - _lastRechargeTime >= rechargeInterval)
|
|
{
|
|
if (_currentResources.Value < maxResources)
|
|
{
|
|
int rechargeAmountToAdd = Mathf.Min(rechargeAmount, maxResources - _currentResources.Value);
|
|
_currentResources.Value += rechargeAmountToAdd;
|
|
|
|
// Debug.Log($"{resourceName} {rechargeAmountToAdd} 충전됨. 현재: {_currentResources.Value}/{maxResources}");
|
|
}
|
|
|
|
_lastRechargeTime = Time.time;
|
|
}
|
|
}
|
|
|
|
public bool CanInteract(ulong playerId)
|
|
{
|
|
// 자원 노드에 자원이 없으면 상호작용 불가
|
|
if (_currentResources.Value <= 0)
|
|
return false;
|
|
|
|
// 쿨다운 확인
|
|
if (Time.time - _lastGatheringTime < gatheringCooldown)
|
|
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;
|
|
|
|
GatherResourceServerRpc(playerId);
|
|
}
|
|
|
|
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
|
private void GatherResourceServerRpc(ulong playerId)
|
|
{
|
|
if (!CanInteract(playerId))
|
|
return;
|
|
|
|
// 플레이어의 인벤토리 확인
|
|
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 gatheredAmount = Mathf.Min(
|
|
resourcesPerGathering,
|
|
_currentResources.Value,
|
|
playerAvailableSpace
|
|
);
|
|
|
|
if (gatheredAmount <= 0)
|
|
{
|
|
Debug.Log($"플레이어 {playerId}의 인벤토리가 가득 찼습니다.");
|
|
return;
|
|
}
|
|
|
|
// 자원 차감
|
|
_currentResources.Value -= gatheredAmount;
|
|
_lastGatheringTime = Time.time;
|
|
|
|
// 플레이어에게 자원 추가
|
|
playerInventory.AddResourceServerRpc(gatheredAmount);
|
|
|
|
Debug.Log($"플레이어 {playerId}가 {gatheredAmount} {resourceName}을(를) 채집했습니다. 남은 자원: {_currentResources.Value}");
|
|
|
|
ShowGatheringEffectClientRpc();
|
|
}
|
|
|
|
[Rpc(SendTo.ClientsAndHost)]
|
|
private void ShowGatheringEffectClientRpc()
|
|
{
|
|
if (gatheringEffectPrefab != null && effectSpawnPoint != null)
|
|
{
|
|
GameObject effect = Instantiate(gatheringEffectPrefab, effectSpawnPoint.position, effectSpawnPoint.rotation);
|
|
Destroy(effect, 2f);
|
|
}
|
|
}
|
|
|
|
public string GetInteractionPrompt()
|
|
{
|
|
if (_currentResources.Value <= 0)
|
|
return "자원 충전 중...";
|
|
|
|
return $"[E] {resourceName} 채집 ({_currentResources.Value}/{maxResources})";
|
|
}
|
|
|
|
public string GetInteractionAnimation()
|
|
{
|
|
return interactionAnimationTrigger;
|
|
}
|
|
|
|
public InteractionEquipmentData GetEquipmentData()
|
|
{
|
|
return equipmentData;
|
|
}
|
|
|
|
public Transform GetTransform()
|
|
{
|
|
return transform;
|
|
}
|
|
}
|
|
} |