diff --git a/Assets/DefaultNetworkPrefabs.asset b/Assets/DefaultNetworkPrefabs.asset new file mode 100644 index 0000000..742cf70 --- /dev/null +++ b/Assets/DefaultNetworkPrefabs.asset @@ -0,0 +1,31 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e651dbb3fbac04af2b8f5abf007ddc23, type: 3} + m_Name: DefaultNetworkPrefabs + m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkPrefabsList + IsDefault: 1 + List: + - Override: 0 + Prefab: {fileID: 3510981371713521867, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} + SourcePrefabToOverride: {fileID: 0} + SourceHashToOverride: 0 + OverridingTargetPrefab: {fileID: 0} + - Override: 0 + Prefab: {fileID: 5508335275054701003, guid: 6b0b58e8352625343951db00beb8cb0a, type: 3} + SourcePrefabToOverride: {fileID: 0} + SourceHashToOverride: 0 + OverridingTargetPrefab: {fileID: 0} + - Override: 0 + Prefab: {fileID: 5384024074013944205, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3} + SourcePrefabToOverride: {fileID: 0} + SourceHashToOverride: 0 + OverridingTargetPrefab: {fileID: 0} diff --git a/Assets/DefaultNetworkPrefabs.asset.meta b/Assets/DefaultNetworkPrefabs.asset.meta new file mode 100644 index 0000000..97a992c --- /dev/null +++ b/Assets/DefaultNetworkPrefabs.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 231a4db0603e8994f9e13e19108d58d1 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Player.prefab b/Assets/Prefabs/Player.prefab index 1d38dd3..0e76bc0 100644 --- a/Assets/Prefabs/Player.prefab +++ b/Assets/Prefabs/Player.prefab @@ -45,6 +45,9 @@ GameObject: - component: {fileID: 4587432968399885263} - component: {fileID: 3810343734243857883} - component: {fileID: 273411532115212066} + - component: {fileID: 1557561356852236266} + - component: {fileID: 6847253018511389861} + - component: {fileID: 8574096554986372233} m_Layer: 0 m_Name: Player m_TagString: Player @@ -208,6 +211,91 @@ MonoBehaviour: m_EditorClassIdentifier: Assembly-CSharp::PlayerScaler scale: 1 scaleJumpAndGravity: 1 +--- !u!114 &1557561356852236266 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5384024074013944205} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject + GlobalObjectIdHash: 0 + InScenePlacedSourceGlobalObjectIdHash: 0 + DeferredDespawnTick: 0 + Ownership: 1 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + k__BackingField: 0 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 + SyncOwnerTransformWhenParented: 1 + AllowOwnerToParent: 0 +--- !u!114 &6847253018511389861 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5384024074013944205} + 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: 0 + RotationInterpolationType: 0 + ScaleInterpolationType: 0 + PositionLerpSmoothing: 1 + PositionMaxInterpolationTime: 0.1 + RotationLerpSmoothing: 1 + RotationMaxInterpolationTime: 0.1 + ScaleLerpSmoothing: 1 + ScaleMaxInterpolationTime: 0.1 + AuthorityMode: 1 + 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 &8574096554986372233 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5384024074013944205} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fce6d601a5d475943bc43d2abd75570d, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::NetworkPlayerSetup + ShowTopMostFoldoutHeaderGroup: 1 --- !u!1 &6840099669803454162 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 629f751..7002168 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -735,7 +735,7 @@ MonoBehaviour: m_StreamingVersion: 20241001 m_LegacyPriority: 0 Target: - TrackingTarget: {fileID: 5297240775790447668} + TrackingTarget: {fileID: 0} LookAtTarget: {fileID: 0} CustomLookAtTarget: 0 Lens: @@ -1218,6 +1218,127 @@ Transform: m_Children: [] m_Father: {fileID: 347639557} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &284910513 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 284910517} + - component: {fileID: 284910516} + - component: {fileID: 284910515} + - component: {fileID: 284910514} + m_Layer: 0 + m_Name: NetworkManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &284910514 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 284910513} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 519095f0598dfdf4ebe457561f77771c, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::NetworkBootstrap + showGui: 1 + enableHotkeys: 1 +--- !u!114 &284910515 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 284910513} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6960e84d07fb87f47956e7a81d71c4e6, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.Transports.UTP.UnityTransport + m_ProtocolType: 0 + m_UseWebSockets: 0 + m_UseEncryption: 0 + m_MaxPacketQueueSize: 128 + m_MaxPayloadSize: 6144 + m_HeartbeatTimeoutMS: 500 + m_ConnectTimeoutMS: 1000 + m_MaxConnectAttempts: 60 + m_DisconnectTimeoutMS: 30000 + ConnectionData: + Address: 127.0.0.1 + Port: 7777 + WebSocketPath: + ServerListenAddress: 0.0.0.0 + ClientBindPort: 0 + DebugSimulator: + PacketDelayMS: 0 + PacketJitterMS: 0 + PacketDropRate: 0 +--- !u!114 &284910516 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 284910513} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 593a2fe42fa9d37498c96f9a383b6521, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkManager + NetworkManagerExpanded: 0 + NetworkConfig: + ProtocolVersion: 0 + NetworkTransport: {fileID: 284910515} + PlayerPrefab: {fileID: 5384024074013944205, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3} + Prefabs: + NetworkPrefabsLists: + - {fileID: 11400000, guid: 231a4db0603e8994f9e13e19108d58d1, type: 2} + TickRate: 30 + ClientConnectionBufferTimeout: 10 + ConnectionApproval: 0 + ConnectionData: + EnableTimeResync: 0 + TimeResyncInterval: 30 + EnsureNetworkVariableLengthSafety: 0 + EnableSceneManagement: 1 + ForceSamePrefabs: 1 + RecycleNetworkIds: 1 + NetworkIdRecycleDelay: 120 + RpcHashSize: 0 + LoadSceneTimeOut: 120 + SpawnTimeout: 10 + EnableNetworkLogs: 1 + NetworkTopology: 0 + UseCMBService: 0 + AutoSpawnPlayerPrefabClientSide: 1 + NetworkProfilingMetrics: 1 + OldPrefabList: [] + RunInBackground: 1 + LogLevel: 1 +--- !u!4 &284910517 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 284910513} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &286369291 GameObject: m_ObjectHideFlags: 0 @@ -2541,9 +2662,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 43b8f1dc43642294f99fab0aaabf6197, type: 3} m_Name: m_EditorClassIdentifier: Assembly-CSharp::FirstPersonController - cameraTarget: {fileID: 897939465} + cameraTarget: {fileID: 0} hiddenRenderers: - - {fileID: 1294962561} + - {fileID: 0} horizontalSensitivity: 0.1 verticalSensitivity: 0.075 invertY: 0 @@ -3737,7 +3858,7 @@ Transform: m_GameObject: {fileID: 829281440} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -2, y: 0.5, z: 1} + m_LocalPosition: {x: -2, y: 0.5, z: 1.5} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] @@ -4063,11 +4184,6 @@ MeshCollider: m_Convex: 0 m_CookingOptions: 30 m_Mesh: {fileID: 4300000, guid: 6d5becbf770f24fa3ab1ceaba45fcefa, type: 3} ---- !u!4 &897939465 stripped -Transform: - m_CorrespondingSourceObject: {fileID: 5751241787949053935, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - m_PrefabInstance: {fileID: 5297240775790447667} - m_PrefabAsset: {fileID: 0} --- !u!1001 &924705986 PrefabInstance: m_ObjectHideFlags: 0 @@ -4633,17 +4749,6 @@ Transform: m_CorrespondingSourceObject: {fileID: 411130, guid: a4bb788560e5d4617b970cd301097f38, type: 3} m_PrefabInstance: {fileID: 1039758568} m_PrefabAsset: {fileID: 0} ---- !u!114 &1141039642 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 8381518232634759850, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - m_PrefabInstance: {fileID: 5297240775790447667} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 463b6be548abf464287096e1e92fcd01, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::PlayerCharacterController --- !u!1001 &1148993634 PrefabInstance: m_ObjectHideFlags: 0 @@ -5113,11 +5218,6 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!137 &1294962561 stripped -SkinnedMeshRenderer: - m_CorrespondingSourceObject: {fileID: 8001664246499114791, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - m_PrefabInstance: {fileID: 5297240775790447667} - m_PrefabAsset: {fileID: 0} --- !u!1001 &1317768121 PrefabInstance: m_ObjectHideFlags: 0 @@ -5904,7 +6004,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 730466b26610d95498d22ab748d855a7, type: 3} m_Name: m_EditorClassIdentifier: Assembly-CSharp::GameModeManager - player: {fileID: 1141039642} + player: {fileID: 0} cameraInput: {fileID: 172071431} painter: {fileID: 0} freeCam: {fileID: 1282734304} @@ -7782,68 +7882,6 @@ Transform: m_CorrespondingSourceObject: {fileID: 4922444305696846, guid: ac1cc01cb5dbf5d4f869c403b38f8a21, type: 3} m_PrefabInstance: {fileID: 1424346480} m_PrefabAsset: {fileID: 0} ---- !u!1001 &5297240775790447667 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - serializedVersion: 3 - m_TransformParent: {fileID: 0} - m_Modifications: - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 3510981371713521867, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - propertyPath: m_Name - value: Player - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} ---- !u!4 &5297240775790447668 stripped -Transform: - m_CorrespondingSourceObject: {fileID: 5067936922952835876, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3} - m_PrefabInstance: {fileID: 5297240775790447667} - m_PrefabAsset: {fileID: 0} --- !u!1660057539 &9223372036854775807 SceneRoots: m_ObjectHideFlags: 0 @@ -7857,7 +7895,7 @@ SceneRoots: - {fileID: 832575519} - {fileID: 410087041} - {fileID: 2025317892} - - {fileID: 5297240775790447667} - {fileID: 686187287} - {fileID: 489277934} - {fileID: 347639557} + - {fileID: 284910517} diff --git a/Assets/Scripts/FirstPersonController.cs b/Assets/Scripts/FirstPersonController.cs index 2932e6d..1cd5fb8 100644 --- a/Assets/Scripts/FirstPersonController.cs +++ b/Assets/Scripts/FirstPersonController.cs @@ -175,6 +175,22 @@ public class FirstPersonController : MonoBehaviour if (r) r.enabled = !hidden; } + /// + /// Explicitly binds this rig to the locally-owned networked player (overriding the scene-wide + /// auto-resolve, which could otherwise latch onto a remote avatar). Called by the GameModeManager + /// when the local player spawns. + /// + public void SetPlayer(PlayerCharacterController p) + { + if (!p) return; + _player = p; + _poseController = p.GetComponent(); + Transform t = p.transform.Find("CameraTarget"); + if (t) cameraTarget = t; + hiddenRenderers = p.GetComponentsInChildren(true); + _resolved = true; + } + void ResolveReferences() { if (_resolved) return; diff --git a/Assets/Scripts/GameModeManager.cs b/Assets/Scripts/GameModeManager.cs index 6f4cdab..3b6a91b 100644 --- a/Assets/Scripts/GameModeManager.cs +++ b/Assets/Scripts/GameModeManager.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using UnityEngine; +using Unity.Cinemachine; #if ENABLE_INPUT_SYSTEM using UnityEngine.InputSystem; #endif @@ -108,6 +109,41 @@ public class GameModeManager : MonoBehaviour m.Bind(this); } + /// + /// Binds the scene singletons (this manager, the orbit/first-person cameras, the painter) to the + /// locally-owned networked player after it spawns, then enters Player Control. Called from + /// on the owning client. Before this runs the scene has no player, + /// so the cycle sits in a player-less mode (Paint); this promotes it once the avatar exists. + /// + public void BindLocalPlayer(PlayerCharacterController localPlayer) + { + if (!localPlayer) return; + player = localPlayer; + + // The painter lives on the player (per-avatar), so bind the local one. + if (!painter) painter = localPlayer.GetComponentInChildren(true); + + Transform camTarget = localPlayer.transform.Find("CameraTarget"); + + // Re-point the third-person orbit camera (Cinemachine Follow/LookAt) at the local avatar. + if (cameraInput) + { + var vcam = cameraInput.GetComponent(); + if (vcam) { vcam.Follow = camTarget; vcam.LookAt = camTarget; } + } + + if (firstPerson) + firstPerson.SetPlayer(localPlayer); + + // Tear down the pre-spawn (player-less) mode and rebuild with Player Control available. + ActiveMode?.Exit(); + _activeIndex = -1; + BuildModes(); + + int idx = _modes.FindIndex(m => m is PlayerControlMode); + SwitchTo(idx >= 0 ? idx : Mathf.Clamp(startModeIndex, 0, _modes.Count - 1)); + } + private void Update() { if (_modes.Count == 0) return; diff --git a/Assets/Scripts/NetworkBootstrap.cs b/Assets/Scripts/NetworkBootstrap.cs new file mode 100644 index 0000000..6ec9573 --- /dev/null +++ b/Assets/Scripts/NetworkBootstrap.cs @@ -0,0 +1,69 @@ +using Unity.Netcode; +using UnityEngine; +#if ENABLE_INPUT_SYSTEM +using UnityEngine.InputSystem; +#endif + +/// +/// Dev-only connection harness for local multiplayer testing across the junction-mirror clones: +/// one instance clicks Host, the others click Client (loopback 127.0.0.1 via the configured +/// UnityTransport). Draws a small on-screen panel and exposes hotkeys (H = Host, C = Client, +/// J = Server, K = Shutdown). Purely a testing scaffold — replace with real lobby/menu UI later. +/// Attach to the same GameObject as the NetworkManager. +/// +[RequireComponent(typeof(NetworkManager))] +[DisallowMultipleComponent] +public class NetworkBootstrap : MonoBehaviour +{ + [Tooltip("Draw the on-screen Host/Client panel (top-left).")] + public bool showGui = true; + + [Tooltip("Allow the H/C/J/K keyboard shortcuts.")] + public bool enableHotkeys = true; + + private NetworkManager _net; + + private void Awake() => _net = GetComponent(); + + private void Update() + { + if (!enableHotkeys) return; +#if ENABLE_INPUT_SYSTEM + var kb = Keyboard.current; + if (kb == null || _net == null) return; + if (!_net.IsListening) + { + if (kb.hKey.wasPressedThisFrame) _net.StartHost(); + else if (kb.cKey.wasPressedThisFrame) _net.StartClient(); + else if (kb.jKey.wasPressedThisFrame) _net.StartServer(); + } + else if (kb.kKey.wasPressedThisFrame) + { + _net.Shutdown(); + } +#endif + } + + private void OnGUI() + { + if (!showGui || _net == null) return; + + GUILayout.BeginArea(new Rect(10, 10, 220, 160), GUI.skin.box); + if (!_net.IsListening) + { + GUILayout.Label("Netcode (dev)"); + if (GUILayout.Button("Host (H)")) _net.StartHost(); + if (GUILayout.Button("Client (C)")) _net.StartClient(); + if (GUILayout.Button("Server (J)")) _net.StartServer(); + } + else + { + string role = _net.IsHost ? "Host" : _net.IsServer ? "Server" : "Client"; + GUILayout.Label($"Role: {role}"); + GUILayout.Label($"ClientId: {_net.LocalClientId}"); + GUILayout.Label($"Clients: {(_net.IsServer ? _net.ConnectedClients.Count : (_net.IsConnectedClient ? 1 : 0))}"); + if (GUILayout.Button("Shutdown (K)")) _net.Shutdown(); + } + GUILayout.EndArea(); + } +} diff --git a/Assets/Scripts/NetworkBootstrap.cs.meta b/Assets/Scripts/NetworkBootstrap.cs.meta new file mode 100644 index 0000000..082fa23 --- /dev/null +++ b/Assets/Scripts/NetworkBootstrap.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 519095f0598dfdf4ebe457561f77771c \ No newline at end of file diff --git a/Assets/Scripts/NetworkPlayerSetup.cs b/Assets/Scripts/NetworkPlayerSetup.cs new file mode 100644 index 0000000..4f28e39 --- /dev/null +++ b/Assets/Scripts/NetworkPlayerSetup.cs @@ -0,0 +1,32 @@ +using Unity.Netcode; +using UnityEngine; + +/// +/// Per-avatar network glue on the spawned player. The local owner binds the scene singletons +/// (GameModeManager, cameras) to itself via ; remote +/// avatars stop simulating so their transform is driven purely by the NetworkTransform replication. +/// Position-sync milestone: remote avatars still show their mesh/idle pose, just no local control. +/// +[RequireComponent(typeof(PlayerCharacterController))] +[DisallowMultipleComponent] +public class NetworkPlayerSetup : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + var controller = GetComponent(); + + if (IsOwner) + { + var manager = FindFirstObjectByType(FindObjectsInactive.Include); + if (manager) + manager.BindLocalPlayer(controller); + return; + } + + // Remote avatar: NetworkTransform owns the transform here, so disable the local + // simulation (input/movement) and the CharacterController's own depenetration. + if (controller) controller.enabled = false; + var cc = GetComponent(); + if (cc) cc.enabled = false; + } +} diff --git a/Assets/Scripts/NetworkPlayerSetup.cs.meta b/Assets/Scripts/NetworkPlayerSetup.cs.meta new file mode 100644 index 0000000..bbd8861 --- /dev/null +++ b/Assets/Scripts/NetworkPlayerSetup.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: fce6d601a5d475943bc43d2abd75570d \ No newline at end of file diff --git a/Packages/manifest.json b/Packages/manifest.json index 9d05b00..5e2abd8 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -5,6 +5,7 @@ "com.unity.ide.visualstudio": "2.0.27", "com.unity.inputsystem": "1.19.0", "com.unity.multiplayer.center": "1.0.1", + "com.unity.netcode.gameobjects": "2.13.0", "com.unity.render-pipelines.universal": "17.3.0", "com.unity.timeline": "1.8.12", "com.unity.ugui": "2.0.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 5d92fcd..685dd7c 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -89,9 +89,19 @@ "com.unity.modules.uielements": "1.0.0" } }, + "com.unity.netcode.gameobjects": { + "version": "2.13.0", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.transport": "2.6.0", + "com.unity.nuget.mono-cecil": "1.11.4" + }, + "url": "https://packages.unity.com" + }, "com.unity.nuget.mono-cecil": { "version": "1.11.6", - "depth": 3, + "depth": 1, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" @@ -201,6 +211,17 @@ }, "url": "https://packages.unity.com" }, + "com.unity.transport": { + "version": "2.6.0", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.burst": "1.8.24", + "com.unity.collections": "2.2.1", + "com.unity.mathematics": "1.3.2" + }, + "url": "https://packages.unity.com" + }, "com.unity.ugui": { "version": "2.0.0", "depth": 0, diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 1938a07..1a44549 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -12,7 +12,7 @@ PlayerSettings: targetDevice: 2 useOnDemandResources: 0 accelerometerFrequency: 60 - companyName: DefaultCompany + companyName: Tausi Development productName: Chameleon defaultCursor: {fileID: 0} cursorHotspot: {x: 0, y: 0}