The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). ## [1.11.0] - 2024-08-20 ### Added - Added `NetworkVariable.CheckDirtyState` that is to be used in tandem with collections in order to detect whether the collection or an item within the collection has changed. (#3005) ### Fixed - Fixed issue by adding null checks in `NetworkVariableBase.CanClientRead` and `NetworkVariableBase.CanClientWrite` methods to ensure safe access to `NetworkBehaviour`. (#3011) - Fixed issue using collections within `NetworkVariable` where the collection would not detect changes to items or nested items. (#3005) - Fixed issue where `List`, `Dictionary`, and `HashSet` collections would not uniquely duplicate nested collections. (#3005) - Fixed Issue where a state with dual triggers, inbound and outbound, could cause a false layer to layer state transition message to be sent to non-authority `NetworkAnimator` instances and cause a warning message to be logged. (#2999) - Fixed issue where `FixedStringSerializer<T>` was using `NetworkVariableSerialization<byte>.AreEqual` to determine if two bytes were equal causes an exception to be thrown due to no byte serializer having been defined. (#2992) ### Changed - Changed permissions exception thrown in `NetworkList` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3005) - Changed permissions exception thrown in `NetworkVariable.Value` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3005)
This commit is contained in:
21
CHANGELOG.md
21
CHANGELOG.md
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com).
|
||||
|
||||
## [1.11.0] - 2024-08-20
|
||||
|
||||
### Added
|
||||
|
||||
- Added `NetworkVariable.CheckDirtyState` that is to be used in tandem with collections in order to detect whether the collection or an item within the collection has changed. (#3005)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed issue by adding null checks in `NetworkVariableBase.CanClientRead` and `NetworkVariableBase.CanClientWrite` methods to ensure safe access to `NetworkBehaviour`. (#3011)
|
||||
- Fixed issue using collections within `NetworkVariable` where the collection would not detect changes to items or nested items. (#3005)
|
||||
- Fixed issue where `List`, `Dictionary`, and `HashSet` collections would not uniquely duplicate nested collections. (#3005)
|
||||
- Fixed Issue where a state with dual triggers, inbound and outbound, could cause a false layer to layer state transition message to be sent to non-authority `NetworkAnimator` instances and cause a warning message to be logged. (#2999)
|
||||
- Fixed issue where `FixedStringSerializer<T>` was using `NetworkVariableSerialization<byte>.AreEqual` to determine if two bytes were equal causes an exception to be thrown due to no byte serializer having been defined. (#2992)
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed permissions exception thrown in `NetworkList` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3005)
|
||||
- Changed permissions exception thrown in `NetworkVariable.Value` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3005)
|
||||
|
||||
|
||||
## [1.10.0] - 2024-07-22
|
||||
|
||||
### Added
|
||||
|
||||
@@ -832,7 +832,12 @@ namespace Unity.Netcode.Components
|
||||
stateChangeDetected = true;
|
||||
//Debug.Log($"[Cross-Fade] To-Hash: {nt.fullPathHash} | TI-Duration: ({tt.duration}) | TI-Norm: ({tt.normalizedTime}) | From-Hash: ({m_AnimationHash[layer]}) | SI-FPHash: ({st.fullPathHash}) | SI-Norm: ({st.normalizedTime})");
|
||||
}
|
||||
else if (!tt.anyState && tt.fullPathHash != m_TransitionHash[layer])
|
||||
// If we are not transitioned into the "any state" and the animator transition isn't a full path hash (layer to layer) and our pre-built destination state to transition does not contain the
|
||||
// current layer (i.e. transitioning into a state from another layer) =or= we do contain the layer and the layer contains state to transition to is contained within our pre-built destination
|
||||
// state then we can handle this transition as a non-cross fade state transition between layers.
|
||||
// Otherwise, if we don't enter into this then this is a "trigger transition to some state that is now being transitioned back to the Idle state via trigger" or "Dual Triggers" IDLE<-->State.
|
||||
else if (!tt.anyState && tt.fullPathHash != m_TransitionHash[layer] && (!m_DestinationStateToTransitioninfo.ContainsKey(layer) ||
|
||||
(m_DestinationStateToTransitioninfo.ContainsKey(layer) && m_DestinationStateToTransitioninfo[layer].ContainsKey(nt.fullPathHash))))
|
||||
{
|
||||
// first time in this transition for this layer
|
||||
m_TransitionHash[layer] = tt.fullPathHash;
|
||||
@@ -841,6 +846,10 @@ namespace Unity.Netcode.Components
|
||||
animState.CrossFade = false;
|
||||
animState.Transition = true;
|
||||
animState.NormalizedTime = tt.normalizedTime;
|
||||
if (m_DestinationStateToTransitioninfo.ContainsKey(layer) && m_DestinationStateToTransitioninfo[layer].ContainsKey(nt.fullPathHash))
|
||||
{
|
||||
animState.DestinationStateHash = nt.fullPathHash;
|
||||
}
|
||||
stateChangeDetected = true;
|
||||
//Debug.Log($"[Transition] TI-Duration: ({tt.duration}) | TI-Norm: ({tt.normalizedTime}) | From-Hash: ({m_AnimationHash[layer]}) |SI-FPHash: ({st.fullPathHash}) | SI-Norm: ({st.normalizedTime})");
|
||||
}
|
||||
|
||||
@@ -758,7 +758,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the local client gains ownership of this object
|
||||
/// Invoked on both the server and the local client of the owner when <see cref="Netcode.NetworkObject"/> ownership is assigned.
|
||||
/// </summary>
|
||||
public virtual void OnGainedOwnership() { }
|
||||
|
||||
@@ -786,7 +786,8 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when we loose ownership of this object
|
||||
/// Invoked on the local client when it loses ownership of the associated <see cref="Netcode.NetworkObject"/>.
|
||||
/// This method is also invoked on the server when any client loses ownership.
|
||||
/// </summary>
|
||||
public virtual void OnLostOwnership() { }
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ namespace Unity.Netcode
|
||||
#pragma warning restore IDE0001
|
||||
[Serializable]
|
||||
[GenerateSerializationForGenericParameter(0)]
|
||||
[GenerateSerializationForType(typeof(byte))]
|
||||
public class AnticipatedNetworkVariable<T> : NetworkVariableBase
|
||||
{
|
||||
[SerializeField]
|
||||
|
||||
@@ -369,7 +369,8 @@ namespace Unity.Netcode
|
||||
// check write permissions
|
||||
if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId))
|
||||
{
|
||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
||||
LogWritePermissionError();
|
||||
return;
|
||||
}
|
||||
|
||||
m_List.Add(item);
|
||||
@@ -390,7 +391,8 @@ namespace Unity.Netcode
|
||||
// check write permissions
|
||||
if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId))
|
||||
{
|
||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
||||
LogWritePermissionError();
|
||||
return;
|
||||
}
|
||||
|
||||
m_List.Clear();
|
||||
@@ -416,7 +418,8 @@ namespace Unity.Netcode
|
||||
// check write permissions
|
||||
if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId))
|
||||
{
|
||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
||||
LogWritePermissionError();
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = m_List.IndexOf(item);
|
||||
@@ -451,7 +454,8 @@ namespace Unity.Netcode
|
||||
// check write permissions
|
||||
if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId))
|
||||
{
|
||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
||||
LogWritePermissionError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < m_List.Length)
|
||||
@@ -480,7 +484,8 @@ namespace Unity.Netcode
|
||||
// check write permissions
|
||||
if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId))
|
||||
{
|
||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
||||
LogWritePermissionError();
|
||||
return;
|
||||
}
|
||||
|
||||
var value = m_List[index];
|
||||
@@ -505,7 +510,8 @@ namespace Unity.Netcode
|
||||
// check write permissions
|
||||
if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId))
|
||||
{
|
||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkList");
|
||||
LogWritePermissionError();
|
||||
return;
|
||||
}
|
||||
|
||||
var previousValue = m_List[index];
|
||||
|
||||
@@ -9,7 +9,6 @@ namespace Unity.Netcode
|
||||
/// <typeparam name="T">the unmanaged type for <see cref="NetworkVariable{T}"/> </typeparam>
|
||||
[Serializable]
|
||||
[GenerateSerializationForGenericParameter(0)]
|
||||
[GenerateSerializationForType(typeof(byte))]
|
||||
public class NetworkVariable<T> : NetworkVariableBase
|
||||
{
|
||||
/// <summary>
|
||||
@@ -80,25 +79,57 @@ namespace Unity.Netcode
|
||||
/// <summary>
|
||||
/// The value of the NetworkVariable container
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When assigning collections to <see cref="Value"/>, unless it is a completely new collection this will not
|
||||
/// detect any deltas with most managed collection classes since assignment of one collection value to another
|
||||
/// is actually just a reference to the collection itself. <br />
|
||||
/// To detect deltas in a collection, you should invoke <see cref="CheckDirtyState"/> after making modifications to the collection.
|
||||
/// </remarks>
|
||||
public virtual T Value
|
||||
{
|
||||
get => m_InternalValue;
|
||||
set
|
||||
{
|
||||
// Compare bitwise
|
||||
if (NetworkVariableSerialization<T>.AreEqual(ref m_InternalValue, ref value))
|
||||
if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId))
|
||||
{
|
||||
LogWritePermissionError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_NetworkBehaviour && !CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId))
|
||||
// Compare the Value being applied to the current value
|
||||
if (!NetworkVariableSerialization<T>.AreEqual(ref m_InternalValue, ref value))
|
||||
{
|
||||
throw new InvalidOperationException("Client is not allowed to write to this NetworkVariable");
|
||||
T previousValue = m_InternalValue;
|
||||
m_InternalValue = value;
|
||||
SetDirty(true);
|
||||
m_IsDisposed = false;
|
||||
OnValueChanged?.Invoke(previousValue, m_InternalValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set(value);
|
||||
/// <summary>
|
||||
/// Invoke this method to check if a collection's items are dirty.
|
||||
/// The default behavior is to exit early if the <see cref="NetworkVariable{T}"/> is already dirty.
|
||||
/// </summary>
|
||||
/// <param name="forceCheck"> when true, this check will force a full item collection check even if the NetworkVariable is already dirty</param>
|
||||
/// <remarks>
|
||||
/// This is to be used as a way to check if a <see cref="NetworkVariable{T}"/> containing a managed collection has any changees to the collection items.<br />
|
||||
/// If you invoked this when a collection is dirty, it will not trigger the <see cref="OnValueChanged"/> unless you set <param name="forceCheck"/> to true. <br />
|
||||
/// </remarks>
|
||||
public bool CheckDirtyState(bool forceCheck = false)
|
||||
{
|
||||
var isDirty = base.IsDirty();
|
||||
|
||||
// Compare the previous with the current if not dirty or forcing a check.
|
||||
if ((!isDirty || forceCheck) && !NetworkVariableSerialization<T>.AreEqual(ref m_PreviousValue, ref m_InternalValue))
|
||||
{
|
||||
SetDirty(true);
|
||||
OnValueChanged?.Invoke(m_PreviousValue, m_InternalValue);
|
||||
m_IsDisposed = false;
|
||||
isDirty = true;
|
||||
}
|
||||
return isDirty;
|
||||
}
|
||||
|
||||
internal ref T RefValue()
|
||||
@@ -185,9 +216,8 @@ namespace Unity.Netcode
|
||||
private protected void Set(T value)
|
||||
{
|
||||
SetDirty(true);
|
||||
T previousValue = m_InternalValue;
|
||||
m_InternalValue = value;
|
||||
OnValueChanged?.Invoke(previousValue, m_InternalValue);
|
||||
OnValueChanged?.Invoke(m_PreviousValue, m_InternalValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -206,20 +236,22 @@ namespace Unity.Netcode
|
||||
/// <param name="keepDirtyDelta">Whether or not the container should keep the dirty delta, or mark the delta as consumed</param>
|
||||
public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
|
||||
{
|
||||
// In order to get managed collections to properly have a previous and current value, we have to
|
||||
// duplicate the collection at this point before making any modifications to the current.
|
||||
m_HasPreviousValue = true;
|
||||
NetworkVariableSerialization<T>.Duplicate(m_InternalValue, ref m_PreviousValue);
|
||||
NetworkVariableSerialization<T>.ReadDelta(reader, ref m_InternalValue);
|
||||
|
||||
// todo:
|
||||
// keepDirtyDelta marks a variable received as dirty and causes the server to send the value to clients
|
||||
// In a prefect world, whether a variable was A) modified locally or B) received and needs retransmit
|
||||
// would be stored in different fields
|
||||
|
||||
T previousValue = m_InternalValue;
|
||||
NetworkVariableSerialization<T>.ReadDelta(reader, ref m_InternalValue);
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
SetDirty(true);
|
||||
}
|
||||
|
||||
OnValueChanged?.Invoke(previousValue, m_InternalValue);
|
||||
OnValueChanged?.Invoke(m_PreviousValue, m_InternalValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -32,21 +32,47 @@ namespace Unity.Netcode
|
||||
/// Maintains a link to the associated NetworkBehaviour
|
||||
/// </summary>
|
||||
private protected NetworkBehaviour m_NetworkBehaviour;
|
||||
private NetworkManager m_InternalNetworkManager;
|
||||
|
||||
public NetworkBehaviour GetBehaviour()
|
||||
{
|
||||
return m_NetworkBehaviour;
|
||||
}
|
||||
|
||||
internal string GetWritePermissionError()
|
||||
{
|
||||
return $"|Client-{m_NetworkManager.LocalClientId}|{m_NetworkBehaviour.name}|{Name}| Write permissions ({WritePerm}) for this client instance is not allowed!";
|
||||
}
|
||||
|
||||
internal void LogWritePermissionError()
|
||||
{
|
||||
Debug.LogError(GetWritePermissionError());
|
||||
}
|
||||
|
||||
private protected NetworkManager m_NetworkManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_InternalNetworkManager == null && m_NetworkBehaviour && m_NetworkBehaviour.NetworkObject?.NetworkManager)
|
||||
{
|
||||
m_InternalNetworkManager = m_NetworkBehaviour.NetworkObject?.NetworkManager;
|
||||
}
|
||||
return m_InternalNetworkManager;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the NetworkVariable
|
||||
/// </summary>
|
||||
/// <param name="networkBehaviour">The NetworkBehaviour the NetworkVariable belongs to</param>
|
||||
public void Initialize(NetworkBehaviour networkBehaviour)
|
||||
{
|
||||
m_InternalNetworkManager = null;
|
||||
m_NetworkBehaviour = networkBehaviour;
|
||||
if (m_NetworkBehaviour.NetworkManager)
|
||||
if (m_NetworkBehaviour && m_NetworkBehaviour.NetworkObject?.NetworkManager)
|
||||
{
|
||||
m_InternalNetworkManager = m_NetworkBehaviour.NetworkObject?.NetworkManager;
|
||||
|
||||
if (m_NetworkBehaviour.NetworkManager.NetworkTimeSystem != null)
|
||||
{
|
||||
UpdateLastSentTime();
|
||||
@@ -217,6 +243,11 @@ namespace Unity.Netcode
|
||||
/// <returns>Whether or not the client has permission to read</returns>
|
||||
public bool CanClientRead(ulong clientId)
|
||||
{
|
||||
if (!m_NetworkBehaviour)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ReadPerm)
|
||||
{
|
||||
default:
|
||||
@@ -234,6 +265,11 @@ namespace Unity.Netcode
|
||||
/// <returns>Whether or not the client has permission to write</returns>
|
||||
public bool CanClientWrite(ulong clientId)
|
||||
{
|
||||
if (!m_NetworkBehaviour)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (WritePerm)
|
||||
{
|
||||
default:
|
||||
|
||||
@@ -349,7 +349,10 @@ namespace Unity.Netcode
|
||||
duplicatedValue.Clear();
|
||||
foreach (var item in value)
|
||||
{
|
||||
duplicatedValue.Add(item);
|
||||
// This handles the nested list scenario List<List<T>>
|
||||
T subValue = default;
|
||||
NetworkVariableSerialization<T>.Duplicate(item, ref subValue);
|
||||
duplicatedValue.Add(subValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -421,6 +424,9 @@ namespace Unity.Netcode
|
||||
duplicatedValue.Clear();
|
||||
foreach (var item in value)
|
||||
{
|
||||
// Handles nested HashSets
|
||||
T subValue = default;
|
||||
NetworkVariableSerialization<T>.Duplicate(item, ref subValue);
|
||||
duplicatedValue.Add(item);
|
||||
}
|
||||
}
|
||||
@@ -497,7 +503,12 @@ namespace Unity.Netcode
|
||||
duplicatedValue.Clear();
|
||||
foreach (var item in value)
|
||||
{
|
||||
duplicatedValue.Add(item.Key, item.Value);
|
||||
// Handles nested dictionaries
|
||||
TKey subKey = default;
|
||||
TVal subValue = default;
|
||||
NetworkVariableSerialization<TKey>.Duplicate(item.Key, ref subKey);
|
||||
NetworkVariableSerialization<TVal>.Duplicate(item.Value, ref subValue);
|
||||
duplicatedValue.Add(subKey, subValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -698,7 +709,7 @@ namespace Unity.Netcode
|
||||
{
|
||||
var val = value[i];
|
||||
var prevVal = previousValue[i];
|
||||
if (!NetworkVariableSerialization<byte>.AreEqual(ref val, ref prevVal))
|
||||
if (val != prevVal)
|
||||
{
|
||||
++numChanges;
|
||||
changes.Set(i);
|
||||
@@ -723,19 +734,11 @@ namespace Unity.Netcode
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = value.GetUnsafePtr();
|
||||
byte* prevPtr = previousValue.GetUnsafePtr();
|
||||
for (int i = 0; i < value.Length; ++i)
|
||||
{
|
||||
if (changes.IsSet(i))
|
||||
{
|
||||
if (i < previousValue.Length)
|
||||
{
|
||||
NetworkVariableSerialization<byte>.WriteDelta(writer, ref ptr[i], ref prevPtr[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkVariableSerialization<byte>.Write(writer, ref ptr[i]);
|
||||
}
|
||||
writer.WriteByteSafe(ptr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2994
Tests/Runtime/NetworkVariableCollectionsTests.cs
Normal file
2994
Tests/Runtime/NetworkVariableCollectionsTests.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Tests/Runtime/NetworkVariableCollectionsTests.cs.meta
Normal file
11
Tests/Runtime/NetworkVariableCollectionsTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 939ac41f36685f84e94a4b66ebbb6d8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -254,7 +254,8 @@ namespace Unity.Netcode.RuntimeTests
|
||||
var oldValue = testCompClient.ServerWritable_Position.Value;
|
||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||
|
||||
Assert.That(() => testCompClient.ServerWritable_Position.Value = newValue, Throws.TypeOf<InvalidOperationException>());
|
||||
LogAssert.Expect(LogType.Error, testCompClient.ServerWritable_Position.GetWritePermissionError());
|
||||
testCompClient.ServerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, oldValue);
|
||||
|
||||
yield return WaitForServerWritableAreEqualOnAll();
|
||||
@@ -283,7 +284,8 @@ namespace Unity.Netcode.RuntimeTests
|
||||
var oldValue = testCompServer.OwnerWritable_Position.Value;
|
||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||
|
||||
Assert.That(() => testCompServer.OwnerWritable_Position.Value = newValue, Throws.TypeOf<InvalidOperationException>());
|
||||
LogAssert.Expect(LogType.Error, testCompServer.OwnerWritable_Position.GetWritePermissionError());
|
||||
testCompServer.OwnerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompServer.OwnerWritable_Position, oldValue);
|
||||
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
@@ -589,8 +591,8 @@ namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
InitializeServerAndClients(useHost);
|
||||
|
||||
// client must not be allowed to write to a server auth variable
|
||||
Assert.Throws<InvalidOperationException>(() => m_Player1OnClient1.TheScalar.Value = k_TestVal1);
|
||||
LogAssert.Expect(LogType.Error, m_Player1OnClient1.TheScalar.GetWritePermissionError());
|
||||
m_Player1OnClient1.TheScalar.Value = k_TestVal1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
@@ -130,72 +129,44 @@ namespace Unity.Netcode.RuntimeTests
|
||||
for (var clientWriting = 0; clientWriting < 3; clientWriting++)
|
||||
{
|
||||
// ==== Server-writable NetworkVariable ====
|
||||
var gotException = false;
|
||||
Debug.Log($"Writing to server-write variable on object {objectIndex} on client {clientWriting}");
|
||||
VerboseDebug($"Writing to server-write variable on object {objectIndex} on client {clientWriting}");
|
||||
|
||||
try
|
||||
{
|
||||
nextValueToWrite++;
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.Value = nextValueToWrite;
|
||||
}
|
||||
catch (Exception)
|
||||
if (clientWriting != serverIndex)
|
||||
{
|
||||
gotException = true;
|
||||
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.GetWritePermissionError());
|
||||
}
|
||||
|
||||
// Verify server-owned netvar can only be written by server
|
||||
Debug.Assert(gotException == (clientWriting != serverIndex));
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.Value = nextValueToWrite;
|
||||
|
||||
// ==== Owner-writable NetworkVariable ====
|
||||
gotException = false;
|
||||
Debug.Log($"Writing to owner-write variable on object {objectIndex} on client {clientWriting}");
|
||||
VerboseDebug($"Writing to owner-write variable on object {objectIndex} on client {clientWriting}");
|
||||
|
||||
try
|
||||
{
|
||||
nextValueToWrite++;
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.Value = nextValueToWrite;
|
||||
}
|
||||
catch (Exception)
|
||||
if (clientWriting != objectIndex)
|
||||
{
|
||||
gotException = true;
|
||||
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.GetWritePermissionError());
|
||||
}
|
||||
|
||||
// Verify client-owned netvar can only be written by owner
|
||||
Debug.Assert(gotException == (clientWriting != objectIndex));
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.Value = nextValueToWrite;
|
||||
|
||||
// ==== Server-writable NetworkList ====
|
||||
gotException = false;
|
||||
Debug.Log($"Writing to server-write list on object {objectIndex} on client {clientWriting}");
|
||||
VerboseDebug($"Writing to [Add] server-write NetworkList on object {objectIndex} on client {clientWriting}");
|
||||
|
||||
try
|
||||
{
|
||||
nextValueToWrite++;
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.Add(nextValueToWrite);
|
||||
}
|
||||
catch (Exception)
|
||||
if (clientWriting != serverIndex)
|
||||
{
|
||||
gotException = true;
|
||||
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.GetWritePermissionError());
|
||||
}
|
||||
|
||||
// Verify server-owned networkList can only be written by server
|
||||
Debug.Assert(gotException == (clientWriting != serverIndex));
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.Add(nextValueToWrite);
|
||||
|
||||
// ==== Owner-writable NetworkList ====
|
||||
gotException = false;
|
||||
Debug.Log($"Writing to owner-write list on object {objectIndex} on client {clientWriting}");
|
||||
VerboseDebug($"Writing to [Add] owner-write NetworkList on object {objectIndex} on client {clientWriting}");
|
||||
|
||||
try
|
||||
{
|
||||
nextValueToWrite++;
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.Add(nextValueToWrite);
|
||||
}
|
||||
catch (Exception)
|
||||
if (clientWriting != objectIndex)
|
||||
{
|
||||
gotException = true;
|
||||
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.GetWritePermissionError());
|
||||
}
|
||||
|
||||
// Verify client-owned networkList can only be written by owner
|
||||
Debug.Assert(gotException == (clientWriting != objectIndex));
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.Add(nextValueToWrite);
|
||||
|
||||
yield return WaitForTicks(m_ServerNetworkManager, 5);
|
||||
yield return WaitForTicks(m_ClientNetworkManagers[0], 5);
|
||||
|
||||
10
package.json
10
package.json
@@ -2,23 +2,23 @@
|
||||
"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": "1.10.0",
|
||||
"version": "1.11.0",
|
||||
"unity": "2021.3",
|
||||
"dependencies": {
|
||||
"com.unity.nuget.mono-cecil": "1.10.1",
|
||||
"com.unity.transport": "1.4.0"
|
||||
},
|
||||
"_upm": {
|
||||
"changelog": "### Added\n\n- Added `NetworkBehaviour.OnNetworkPreSpawn` and `NetworkBehaviour.OnNetworkPostSpawn` methods that provide the ability to handle pre and post spawning actions during the `NetworkObject` spawn sequence. (#2906)\n- Added a client-side only `NetworkBehaviour.OnNetworkSessionSynchronized` convenience method that is invoked on all `NetworkBehaviour`s after a newly joined client has finished synchronizing with the network session in progress. (#2906)\n- Added `NetworkBehaviour.OnInSceneObjectsSpawned` convenience method that is invoked when all in-scene `NetworkObject`s have been spawned after a scene has been loaded or upon a host or server starting. (#2906)\n\n### Fixed\n\n- Fixed issue where the realtime network stats monitor was not able to display RPC traffic in release builds due to those stats being only available in development builds or the editor. (#2980)\n- Fixed issue where `NetworkManager.ScenesLoaded` was not being updated if `PostSynchronizationSceneUnloading` was set and any loaded scenes not used during synchronization were unloaded.(#2977)\n- Fixed issue where internal delta serialization could not have a byte serializer defined when serializing deltas for other types. Added `[GenerateSerializationForType(typeof(byte))]` to both the `NetworkVariable` and `AnticipatedNetworkVariable` classes to assure a byte serializer is defined. (#2953)\n- Fixed issue with the client count not being correct on the host or server side when a client disconnects itself from a session. (#2941)\n- Fixed issue with the host trying to send itself a message that it has connected when first starting up. (#2941)\n- Fixed issue where in-scene placed NetworkObjects could be destroyed if a client disconnects early and/or before approval. (#2923)\n- Fixed issue where `NetworkDeltaPosition` would \"jitter\" periodically if both unreliable delta state updates and half-floats were used together. (#2922)\n- Fixed issue where `NetworkRigidbody2D` would not properly change body type based on the instance's authority when spawned. (#2916)\n- Fixed issue where a `NetworkObject` component's associated `NetworkBehaviour` components would not be detected if scene loading is disabled in the editor and the currently loaded scene has in-scene placed `NetworkObject`s. (#2906)\n- Fixed issue where an in-scene placed `NetworkObject` with `NetworkTransform` that is also parented under a `GameObject` would not properly synchronize when the parent `GameObject` had a world space position other than 0,0,0. (#2895)\n\n### Changed"
|
||||
"changelog": "### Added\n\n- Added `NetworkVariable.CheckDirtyState` that is to be used in tandem with collections in order to detect whether the collection or an item within the collection has changed. (#3005)\n\n### Fixed\n\n- Fixed issue by adding null checks in `NetworkVariableBase.CanClientRead` and `NetworkVariableBase.CanClientWrite` methods to ensure safe access to `NetworkBehaviour`. (#3011)\n- Fixed issue using collections within `NetworkVariable` where the collection would not detect changes to items or nested items. (#3005)\n- Fixed issue where `List`, `Dictionary`, and `HashSet` collections would not uniquely duplicate nested collections. (#3005)\n- Fixed Issue where a state with dual triggers, inbound and outbound, could cause a false layer to layer state transition message to be sent to non-authority `NetworkAnimator` instances and cause a warning message to be logged. (#2999)\n- Fixed issue where `FixedStringSerializer<T>` was using `NetworkVariableSerialization<byte>.AreEqual` to determine if two bytes were equal causes an exception to be thrown due to no byte serializer having been defined. (#2992)\n\n### Changed\n\n- Changed permissions exception thrown in `NetworkList` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3005)\n- Changed permissions exception thrown in `NetworkVariable.Value` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3005)"
|
||||
},
|
||||
"upmCi": {
|
||||
"footprint": "f100032a819fdef7edacd4fdfa133b189f94ef7d"
|
||||
"footprint": "aa624034952045f7f2399c1f99fd31b764234959"
|
||||
},
|
||||
"documentationUrl": "https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@1.10/manual/index.html",
|
||||
"documentationUrl": "https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@1.11/manual/index.html",
|
||||
"repository": {
|
||||
"url": "https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git",
|
||||
"type": "git",
|
||||
"revision": "a342c8ddce87ae46a30dffbebb8f87ac364c0a87"
|
||||
"revision": "e3303ba66b4a642ccf0bc72104107e1b8e1ebe1c"
|
||||
},
|
||||
"samples": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user