From 871ccbc5aa94370f88cb692542f902d7151e28ed Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Sat, 2 May 2026 12:21:42 -0500 Subject: [PATCH 1/3] update - changelog Updating changelog entry. --- com.unity.netcode.gameobjects/CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 063b6c3375..9d1075d0b3 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -22,7 +22,6 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Fixed -- Fixed issue where if the `NetworkManager` player prefab is not assigned an exception is thrown upon starting a host and/or when a client joins. (#3965) ### Security @@ -30,6 +29,12 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Obsolete +### [2.11.2] - 2026-05-01 + +### Fixed + +- Fixed issue where if the `NetworkManager` player prefab is not assigned an exception is thrown upon starting a host and/or when a client joins. (#3965) + ## [2.11.1] - 2026-04-26 ### Changed From c28f3da1efca1d9a62b86ba5ff48c8e37c68ee88 Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Sat, 2 May 2026 12:22:12 -0500 Subject: [PATCH 2/3] update Adding new NetworkVariable door example used for documentation. --- .../NetworkVariable/DoorExample.cs | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 Examples/DocumentationExamples/NetworkVariable/DoorExample.cs diff --git a/Examples/DocumentationExamples/NetworkVariable/DoorExample.cs b/Examples/DocumentationExamples/NetworkVariable/DoorExample.cs new file mode 100644 index 0000000000..d80ec1bae0 --- /dev/null +++ b/Examples/DocumentationExamples/NetworkVariable/DoorExample.cs @@ -0,0 +1,273 @@ +using System.Runtime.CompilerServices; +using Unity.Netcode; +using UnityEngine; + +/// +/// Example of using a to drive changes +/// in state. +/// +/// +/// This is a simple state driven door example. +/// This script was written with recommended usages patterns in mind. +/// +public class Door : NetworkBehaviour, INetworkUpdateSystem +{ + /// + /// The two door states. + /// + public enum DoorStates + { + Closed, + Open + } + + /// + /// Initializes the door to a specific state (server side) when first spawned. + /// + [Tooltip("Configures the door's initial state when 1st spawned.")] + public DoorStates InitialState = DoorStates.Closed; + + /// + /// Used for example purposes. + /// When true, only the server can open and close the door. + /// Clients will receive a console log saying they could not open the door. + /// + public bool IsLocked; + + /// + /// A simple door state where the server has write permissions and everyone has read permissions. + /// + private NetworkVariable m_State = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); + + /// + /// The current state of the door. + /// + public DoorStates CurrentState => m_State.Value; + + /// + /// Invoked while the is in the middle of + /// being spawned. + /// + public override void OnNetworkSpawn() + { + // The write authority (server) does not need to know about its + // own changes (for this example) since it is the "single point + // of truth" for the door instance. + if (IsServer) + { + // Host/Server: + // Applies the configurable state upon spawning. + m_State.Value = InitialState; + } + else + { + // Clients: + // Subscribe to changes in the door's state. + m_State.OnValueChanged += OnStateChanged; + } + } + + /// + /// Invoked once the door and all associated components + /// have finished the spawn process. + /// + protected override void OnNetworkPostSpawn() + { + // Everyone updates their door state when finished spawning the door + // in order to assure the door reflects (visually) its current state. + UpdateFromState(); + + // Begin to start updating this NetworkBehaviour instance once all + // netcode related components have finished the spawn process. + NetworkUpdateLoop.RegisterNetworkUpdate(this, NetworkUpdateStage.Update); + base.OnNetworkPostSpawn(); + } + + /// + /// Example of using the usage pattern + /// where it only updates while spawned. + /// + /// The current update stage being invoked. + public void NetworkUpdate(NetworkUpdateStage updateStage) + { + switch (updateStage) + { + case NetworkUpdateStage.Update: + { + if (Input.GetKeyDown(KeyCode.Space)) + { + Interact(); + } + break; + } + } + } + + /// + /// Invoked just before this instance runs through its de-spawn + /// sequence. A good time to unsubscribe from things. + /// + public override void OnNetworkPreDespawn() + { + if (!IsServer) + { + m_State.OnValueChanged -= OnStateChanged; + } + + // Stop updating this NetworkBehaviour instance prior to running + // through the de-spawn process. + NetworkUpdateLoop.RegisterNetworkUpdate(this, NetworkUpdateStage.Update); + base.OnNetworkPreDespawn(); + } + + /// + /// Server makes changes to the state. + /// Clients receive the changes in state. + /// + /// + /// When the previous state equals the current state, we are a client + /// that is doing its 1st synchronization of this door instance. + /// + /// The previous state. + /// The current state. + public void OnStateChanged(DoorStates previous, DoorStates current) + { + UpdateFromState(); + } + + /// + /// Invoke when the state is updated in order to apply the change + /// in door state to the door asset itself. + /// + private void UpdateFromState() + { + switch(m_State.Value) + { + case DoorStates.Closed: + { + // door is open: + // - rotate door transform + // - play animations, sound etc. + /// + /// Override to apply specific checks (like a player having the right + /// key to open the door) or make it a non-virtual class and add logic + /// directly to this method. + /// + /// The player attempting to open the door. + /// + protected virtual bool CanPlayerToggleState(NetworkObject player) + { + // For this example, if the door "is locked" then clients will + // not be able to open the door but the host-client's player can. + return !IsLocked || player.IsOwnedByServer; + } + + /// + /// Invoked by either a Host or clients to interact with the door. + /// + public void Interact() + { + // Optional: + // This is only if you want clients to be able to + // interact with doors. A dedicated server would not + // be able to do this since it does not have a player. + if (IsServer && !IsHost) + { + // Optional to log a warning about this. + return; + } + + if (IsHost) + { + ToggleState(NetworkManager.LocalClientId); + } + else + { + // Clients send an RPC to server (write authority) who applies the + // change in state that will be synchronized with all client observers. + ToggleStateRpc(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private DoorStates NextToggleState() + { + return m_State.Value == DoorStates.Open ? DoorStates.Closed : DoorStates.Open; + } + + /// + /// Invoked only server-side + /// Primary method to handle toggling the door state. + /// + /// The client toggling the door state. + private void ToggleState(ulong clientId) + { + // Get the server-side client player instance + var playerObject = NetworkManager.SpawnManager.GetPlayerNetworkObject(clientId); + if (playerObject != null) + { + var nextToggleState = NextToggleState(); + if (CanPlayerToggleState(playerObject)) + { + // Host toggles the state + m_State.Value = nextToggleState; + UpdateFromState(); + } + else + { + ToggleStateFailRpc(nextToggleState, RpcTarget.Single(clientId, RpcTargetUse.Temp)); + } + } + else + { + // Optional as to how you handle this. Since ToggleState is only invoked by + // sever-side only script, this could mean many things depending upon whether + // or not a client could interact with something and not have a player object. + // If that is the case, then don't even bother checking for a player object. + // If that is not the case, then there could be a timing issue between when + // something can be "interacted with" and when a player is about to be de-spawned. + // For this example, we just log a warning as this example was built with + // the requirement that a client has a spawned player object that is used for + // reference to determine if the client's player can toggle the state of the + // door or not. + NetworkLog.LogWarningServer($"Client-{clientId} has no spawned player object!"); + } + } + + /// + /// Invoked by clients. + /// Re-directs to the common method. + /// + /// includes that is automatically populated for you. + [Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)] + private void ToggleStateRpc(RpcParams rpcParams = default) + { + ToggleState(rpcParams.Receive.SenderClientId); + } + + /// + /// Optional: + /// Handling when a player cannot open a door. + /// + /// includes that is automatically populated for you. + [Rpc(SendTo.SpecifiedInParams, InvokePermission = RpcInvokePermission.Server)] + private void ToggleStateFailRpc(DoorStates doorState, RpcParams rpcParams = default) + { + // Provide player feedback that toggling failed. + Debug.Log($"Failed to {doorState} the door!"); + } +} From 5ae7b847ef8f800e93572fe648b1d09dd0937db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chrobot?= Date: Sun, 3 May 2026 16:00:39 +0200 Subject: [PATCH 3/3] updated current package version --- com.unity.netcode.gameobjects/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/package.json b/com.unity.netcode.gameobjects/package.json index d4a1bf74c6..04492deaa0 100644 --- a/com.unity.netcode.gameobjects/package.json +++ b/com.unity.netcode.gameobjects/package.json @@ -2,7 +2,7 @@ "name": "com.unity.netcode.gameobjects", "displayName": "Netcode for GameObjects", "description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.", - "version": "2.11.2", + "version": "2.11.3", "unity": "6000.0", "dependencies": { "com.unity.nuget.mono-cecil": "1.11.4",