일꾼(Worker) 개발 및 Kaykit Adventurer 애셋 추가

코어 오른쪽 건물에서 상호작용 하면 Worker 생성
Worker와 상호작용하면 Worker가 플레이어를 따라옴
그 상태에서 자원과 상호작용하면 Worker를 자원에 배치할 수 있음.
This commit is contained in:
2026-02-01 21:55:14 +09:00
parent 78791649ae
commit 3e747a9d97
799 changed files with 2085932 additions and 80 deletions

View File

@@ -34,12 +34,75 @@ namespace Northbound
public GameObject gatheringEffectPrefab;
public Transform effectSpawnPoint;
[Header("Worker Assignment")]
public bool allowWorkerAssignment = true;
[Header("Multi-worker")]
public bool allowMultipleWorkers = false; // 한 자원에 여러 워커 허용 여부
public bool HasResourcesAvailable()
{
return _currentResources.Value > 0;
}
public bool CanWorkerMineResource(ulong workerId)
{
if (!HasResourcesAvailable())
return false;
if (allowMultipleWorkers)
return true;
if (_currentWorkerId.Value == ulong.MaxValue)
return true;
return _currentWorkerId.Value == workerId;
}
public void TakeResourcesForWorker(int amount, ulong workerId)
{
if (!IsServer) return;
if (!allowMultipleWorkers)
{
if (_currentWorkerId.Value != ulong.MaxValue && _currentWorkerId.Value != workerId)
return;
}
int availableResources = _currentResources.Value;
int actualAmount = Mathf.Min(amount, availableResources);
if (actualAmount <= 0)
return;
_currentResources.Value -= actualAmount;
_lastGatheringTime = Time.time;
if (!allowMultipleWorkers && actualAmount > 0)
{
_currentWorkerId.Value = workerId;
}
if (_currentResources.Value <= 0 && !allowMultipleWorkers)
{
_currentWorkerId.Value = ulong.MaxValue;
}
ShowGatheringEffectClientRpc();
}
private NetworkVariable<int> _currentResources = new NetworkVariable<int>(
0,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server
);
private NetworkVariable<ulong> _currentWorkerId = new NetworkVariable<ulong>(
ulong.MaxValue,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server
);
private float _lastGatheringTime;
private float _lastRechargeTime;
@@ -103,19 +166,51 @@ namespace Northbound
public void Interact(ulong playerId)
{
if (!CanInteract(playerId))
return;
GatherResourceServerRpc(playerId);
AssignOrGatherResourceServerRpc(playerId, NetworkObject.NetworkObjectId);
}
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
private void GatherResourceServerRpc(ulong playerId)
private void AssignOrGatherResourceServerRpc(ulong playerId, ulong resourceId)
{
var playerObject = NetworkManager.Singleton.ConnectedClients[playerId].PlayerObject;
if (playerObject == null)
{
return;
}
var playerInteraction = playerObject.GetComponent<PlayerInteraction>();
bool workerAssigned = false;
if (allowWorkerAssignment && playerInteraction != null && playerInteraction.assignedWorker != null)
{
var worker = playerInteraction.assignedWorker;
if (worker.OwnerPlayerId == playerId && (int)worker.CurrentState == 1)
{
worker.AssignMiningTargetServerRpc(resourceId);
workerAssigned = true;
ShowGatheringEffectClientRpc();
}
}
if (!workerAssigned)
{
if (!CanInteract(playerId))
{
return;
}
GatherResource(playerId);
}
}
private void GatherResource(ulong playerId)
{
if (!CanInteract(playerId))
return;
// 플레이어의 인벤토리 확인
var playerObject = NetworkManager.Singleton.ConnectedClients[playerId].PlayerObject;
if (playerObject == null)
return;
@@ -123,14 +218,11 @@ namespace Northbound
var playerInventory = playerObject.GetComponent<PlayerResourceInventory>();
if (playerInventory == null)
{
Debug.LogWarning($"플레이어 {playerId}에게 PlayerResourceInventory 컴포넌트가 없습니다.");
return;
}
// 플레이어가 받을 수 있는 최대량 계산
int playerAvailableSpace = playerInventory.GetAvailableSpace();
// 자원 노드가 줄 수 있는 양과 플레이어가 받을 수 있는 양 중 작은 값 선택
int gatheredAmount = Mathf.Min(
resourcesPerGathering,
_currentResources.Value,
@@ -139,19 +231,14 @@ namespace Northbound
if (gatheredAmount <= 0)
{
Debug.Log($"플레이어 {playerId}의 인벤토리가 가득 찼습니다.");
return;
}
// 자원 차감
_currentResources.Value -= gatheredAmount;
_lastGatheringTime = Time.time;
// 플레이어에게 자원 추가
playerInventory.AddResourceServerRpc(gatheredAmount);
Debug.Log($"플레이어 {playerId}가 {gatheredAmount} {resourceName}을(를) 채집했습니다. 남은 자원: {_currentResources.Value}");
ShowGatheringEffectClientRpc();
}