diff --git a/Assets/Prefabs/Worker.prefab b/Assets/Prefabs/Worker.prefab index 40d3c4b..a5c5ed3 100644 --- a/Assets/Prefabs/Worker.prefab +++ b/Assets/Prefabs/Worker.prefab @@ -15,6 +15,8 @@ GameObject: - component: {fileID: -6833905931170612921} - component: {fileID: -5642067558840373223} - component: {fileID: 7652614764984268938} + - component: {fileID: 3118986035178891702} + - component: {fileID: -802640627660999798} m_Layer: 7 m_Name: Worker m_TagString: Untagged @@ -31,7 +33,7 @@ Transform: m_GameObject: {fileID: 1348125539835438327} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 5.26293, y: 1.00002, z: -80.92117} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: @@ -102,7 +104,7 @@ MonoBehaviour: maxBagCapacity: 50 miningSpeed: 1 followDistance: 3 - movementSpeed: 10 + movementSpeed: 21.41 resourcesPerMining: 5 interactionAnimationTrigger: miningEffectPrefab: {fileID: 0} @@ -181,10 +183,88 @@ Rigidbody: m_ImplicitCom: 1 m_ImplicitTensor: 1 m_UseGravity: 1 - m_IsKinematic: 0 + m_IsKinematic: 1 m_Interpolate: 0 m_Constraints: 0 m_CollisionDetection: 0 +--- !u!114 &3118986035178891702 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1348125539835438327} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.Components.NetworkTransform + ShowTopMostFoldoutHeaderGroup: 1 + NetworkTransformExpanded: 0 + AutoOwnerAuthorityTickOffset: 1 + PositionInterpolationType: 1 + RotationInterpolationType: 1 + ScaleInterpolationType: 0 + PositionLerpSmoothing: 1 + PositionMaxInterpolationTime: 0.1 + RotationLerpSmoothing: 1 + RotationMaxInterpolationTime: 0.1 + ScaleLerpSmoothing: 1 + ScaleMaxInterpolationTime: 0.1 + AuthorityMode: 0 + TickSyncChildren: 0 + UseUnreliableDeltas: 0 + SyncPositionX: 1 + SyncPositionY: 1 + SyncPositionZ: 1 + SyncRotAngleX: 1 + SyncRotAngleY: 1 + SyncRotAngleZ: 1 + SyncScaleX: 0 + SyncScaleY: 0 + SyncScaleZ: 0 + PositionThreshold: 0.001 + RotAngleThreshold: 0.01 + ScaleThreshold: 0.01 + UseQuaternionSynchronization: 0 + UseQuaternionCompression: 0 + UseHalfFloatPrecision: 0 + InLocalSpace: 0 + SwitchTransformSpaceWhenParented: 0 + Interpolate: 1 + SlerpPosition: 0 +--- !u!114 &-802640627660999798 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1348125539835438327} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e8d0727d5ae3244e3b569694d3912374, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.Components.NetworkAnimator + ShowTopMostFoldoutHeaderGroup: 1 + NetworkAnimatorExpanded: 0 + AuthorityMode: 0 + m_Animator: {fileID: -6833905931170612921} + TransitionStateInfoList: [] + AnimatorParameterEntries: + ParameterEntries: + - name: Idle + NameHash: 2081823275 + Synchronize: 1 + ParameterType: 4 + - name: Walk + NameHash: 765711723 + Synchronize: 1 + ParameterType: 4 + - name: Mine + NameHash: -912622419 + Synchronize: 1 + ParameterType: 4 + AnimatorParametersExpanded: 0 --- !u!1001 &8340426036889336253 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/Scenes/GameMain.unity b/Assets/Scenes/GameMain.unity index 43ad18e..b71e09c 100644 --- a/Assets/Scenes/GameMain.unity +++ b/Assets/Scenes/GameMain.unity @@ -1828,7 +1828,7 @@ MonoBehaviour: m_DisconnectTimeoutMS: 30000 ConnectionData: Address: 127.0.0.1 - Port: 7835 + Port: 7843 ServerListenAddress: 127.0.0.1 ClientBindPort: 0 DebugSimulator: diff --git a/Assets/Scripts/Resource.cs b/Assets/Scripts/Resource.cs index a3662ed..83ccfe3 100644 --- a/Assets/Scripts/Resource.cs +++ b/Assets/Scripts/Resource.cs @@ -163,26 +163,35 @@ namespace Northbound [Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)] private void AssignOrGatherResourceServerRpc(ulong playerId, ulong resourceId) { - var playerObject = NetworkManager.Singleton.ConnectedClients[playerId].PlayerObject; - if (playerObject == null) - { - return; - } + Debug.Log($"[Resource] AssignOrGatherResourceServerRpc called - PlayerID: {playerId}, ResourceID: {resourceId}"); - var playerInteraction = playerObject.GetComponent(); - bool workerAssigned = false; - - if (allowWorkerAssignment && playerInteraction != null && playerInteraction.assignedWorker != null) + + if (allowWorkerAssignment) { - var worker = playerInteraction.assignedWorker; - - if (worker.OwnerPlayerId == playerId && (int)worker.CurrentState == 1) + // Find worker owned by player in Following state (server-side, not client-side) + Worker assignedWorker = FindWorkerForPlayer(playerId); + + if (assignedWorker != null) { - worker.AssignMiningTargetServerRpc(resourceId); - workerAssigned = true; - - ShowGatheringEffectClientRpc(); + Debug.Log($"[Resource] Worker found server-side - OwnerPlayerId: {assignedWorker.OwnerPlayerId}, CurrentState: {(int)assignedWorker.CurrentState}"); + + if ((int)assignedWorker.CurrentState == 1) // 1 = Following + { + Debug.Log($"[Resource] ✓ Assigning worker to resource!"); + assignedWorker.AssignMiningTargetServerRpc(resourceId); + workerAssigned = true; + + ShowGatheringEffectClientRpc(); + } + else + { + Debug.LogWarning($"[Resource] Worker not in Following state! State: {(int)assignedWorker.CurrentState}"); + } + } + else + { + Debug.Log($"[Resource] No worker found for player {playerId} in Following state"); } } @@ -192,7 +201,7 @@ namespace Northbound { return; } - + GatherResource(playerId); } } @@ -274,5 +283,42 @@ namespace Northbound { return transform; } + + private Worker FindWorkerForPlayer(ulong playerId) + { + Debug.Log($"[Resource] FindWorkerForPlayer called - Looking for worker assigned to player {playerId}"); + + if (NetworkManager.Singleton == null || NetworkManager.Singleton.SpawnManager == null) + { + Debug.LogWarning($"[Resource] FindWorkerForPlayer - NetworkManager or SpawnManager is null"); + return null; + } + + var spawnedObjects = NetworkManager.Singleton.SpawnManager.SpawnedObjects; + int objectsChecked = 0; + int workersFound = 0; + + foreach (var kvp in spawnedObjects) + { + var networkObj = kvp.Value; + var worker = networkObj.GetComponent(); + + if (worker != null) + { + workersFound++; + Debug.Log($"[Resource] FindWorkerForPlayer - Found worker: {worker.gameObject.name}, OwnerPlayerId: {worker.OwnerPlayerId}, State: {(int)worker.CurrentState}"); + + // Use worker's internal OwnerPlayerId, NOT NetworkObject.OwnerClientId! + if (worker.OwnerPlayerId == playerId && (int)worker.CurrentState == 1) // 1 = Following + { + Debug.Log($"[Resource] FindWorkerForPlayer - ✓ Found worker: {worker.gameObject.name} for player {playerId}"); + return worker; + } + } + } + + Debug.LogWarning($"[Resource] FindWorkerForPlayer - Checked {objectsChecked} objects, found {workersFound} workers, no matching worker in Following state!"); + return null; + } } } diff --git a/Assets/Scripts/Worker.cs b/Assets/Scripts/Worker.cs index 69532d8..f203b3d 100644 --- a/Assets/Scripts/Worker.cs +++ b/Assets/Scripts/Worker.cs @@ -504,7 +504,8 @@ namespace Northbound var networkObj = kvp.Value; if (networkObj != null && networkObj.OwnerClientId == _ownerPlayerId.Value) { - if (networkObj.gameObject != null) + var playerInteraction = networkObj.GetComponent(); + if (playerInteraction != null && networkObj.gameObject != null) { _playerTransform = networkObj.transform; return true; diff --git a/Assets/Scripts/WorkerSpawner.cs b/Assets/Scripts/WorkerSpawner.cs index 9a512dc..8e31aed 100644 --- a/Assets/Scripts/WorkerSpawner.cs +++ b/Assets/Scripts/WorkerSpawner.cs @@ -94,7 +94,7 @@ namespace Northbound GameObject workerObj = Instantiate(workerPrefab, spawnPosition, Quaternion.identity); NetworkObject workerNetObj = workerObj.GetComponent(); - + if (workerNetObj == null) { Debug.LogError("[WorkerSpawner] Worker prefab must have NetworkObject component"); @@ -102,18 +102,19 @@ namespace Northbound return; } - workerNetObj.Spawn(); - _lastSpawnTime = Time.time; - _workerCount.Value++; + // IMPORTANT: Spawn as server-owned so server can modify worker's NetworkVariables + workerNetObj.Spawn(); + _lastSpawnTime = Time.time; + _workerCount.Value++; - ShowSpawnEffectClientRpc(spawnPosition); + ShowSpawnEffectClientRpc(spawnPosition); - Debug.Log($"[WorkerSpawner] 워커 생성됨 (총 워커: {_workerCount.Value}/{maxWorkers})"); + Debug.Log($"[WorkerSpawner] Worker spawned (server-owned) and assigned to player {playerId} (Total: {_workerCount.Value}/{maxWorkers})"); - ScheduleWorkerAssignment(playerId, workerNetObj.NetworkObjectId); - } + ScheduleWorkerAssignment(playerId, workerNetObj.NetworkObjectId); + } - private void ScheduleWorkerAssignment(ulong playerId, ulong workerNetObjectId) + private void ScheduleWorkerAssignment(ulong playerId, ulong workerNetObjectId) { StartCoroutine(AssignWorkerAfterFrame(playerId, workerNetObjectId)); }