Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.5.2] - 2023-07-24

### Added

### Fixed

- Fixed issue where `NetworkClient.OwnedObjects` was not returning any owned objects due to the `NetworkClient.IsConnected` not being properly set. (#2631)
- Fixed a crash when calling TrySetParent with a null Transform (#2625)
- Fixed issue where a `NetworkTransform` using full precision state updates was losing transform state updates when interpolation was enabled. (#2624)
- Fixed issue where `NetworkObject.SpawnWithObservers` was not being honored for late joining clients. (#2623)
- Fixed issue where invoking `NetworkManager.Shutdown` multiple times, depending upon the timing, could cause an exception. (#2622)
- Fixed issue where removing ownership would not notify the server that it gained ownership. This also resolves the issue where an owner authoritative NetworkTransform would not properly initialize upon removing ownership from a remote client. (#2618)
- Fixed ILPP issues when using CoreCLR and for certain dedicated server builds. (#2614)
- Fixed an ILPP compile error when creating a generic NetworkBehaviour singleton with a static T instance. (#2603)

### Changed
  • Loading branch information
Unity Technologies committed Jul 24, 2023
1 parent 4d70c19 commit 0581a42
Show file tree
Hide file tree
Showing 24 changed files with 390 additions and 169 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com).

## [1.5.2] - 2023-07-24

### Added

### Fixed

- Fixed issue where `NetworkClient.OwnedObjects` was not returning any owned objects due to the `NetworkClient.IsConnected` not being properly set. (#2631)
- Fixed a crash when calling TrySetParent with a null Transform (#2625)
- Fixed issue where a `NetworkTransform` using full precision state updates was losing transform state updates when interpolation was enabled. (#2624)
- Fixed issue where `NetworkObject.SpawnWithObservers` was not being honored for late joining clients. (#2623)
- Fixed issue where invoking `NetworkManager.Shutdown` multiple times, depending upon the timing, could cause an exception. (#2622)
- Fixed issue where removing ownership would not notify the server that it gained ownership. This also resolves the issue where an owner authoritative NetworkTransform would not properly initialize upon removing ownership from a remote client. (#2618)
- Fixed ILPP issues when using CoreCLR and for certain dedicated server builds. (#2614)
- Fixed an ILPP compile error when creating a generic NetworkBehaviour singleton with a static T instance. (#2603)

### Changed

## [1.5.1] - 2023-06-07

### Added
Expand Down
29 changes: 21 additions & 8 deletions Components/NetworkTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1159,8 +1159,11 @@ public Vector3 GetScale(bool getCurrentState = false)
// Non-Authoritative's current position, scale, and rotation that is used to assure the non-authoritative side cannot make adjustments to
// the portions of the transform being synchronized.
private Vector3 m_CurrentPosition;
private Vector3 m_TargetPosition;
private Vector3 m_CurrentScale;
private Vector3 m_TargetScale;
private Quaternion m_CurrentRotation;
private Vector3 m_TargetRotation;


[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -2009,6 +2012,7 @@ private void ApplyTeleportingState(NetworkTransformState newState)
}

m_CurrentPosition = currentPosition;
m_TargetPosition = currentPosition;

// Apply the position
if (newState.InLocalSpace)
Expand All @@ -2026,7 +2030,6 @@ private void ApplyTeleportingState(NetworkTransformState newState)
if (UseHalfFloatPrecision)
{
currentScale = newState.Scale;
m_CurrentScale = currentScale;
}
else
{
Expand All @@ -2049,6 +2052,7 @@ private void ApplyTeleportingState(NetworkTransformState newState)
}

m_CurrentScale = currentScale;
m_TargetScale = currentScale;
m_ScaleInterpolator.ResetTo(currentScale, sentTime);

// Apply the adjusted scale
Expand Down Expand Up @@ -2082,6 +2086,7 @@ private void ApplyTeleportingState(NetworkTransformState newState)
}

m_CurrentRotation = currentRotation;
m_TargetRotation = currentRotation.eulerAngles;
m_RotationInterpolator.ResetTo(currentRotation, sentTime);

if (InLocalSpace)
Expand Down Expand Up @@ -2158,28 +2163,29 @@ private void UpdateState(NetworkTransformState oldState, NetworkTransformState n
}
else
{
var currentPosition = GetSpaceRelativePosition();
var newTargetPosition = m_TargetPosition;
if (m_LocalAuthoritativeNetworkState.HasPositionX)
{
currentPosition.x = m_LocalAuthoritativeNetworkState.PositionX;
newTargetPosition.x = m_LocalAuthoritativeNetworkState.PositionX;
}

if (m_LocalAuthoritativeNetworkState.HasPositionY)
{
currentPosition.y = m_LocalAuthoritativeNetworkState.PositionY;
newTargetPosition.y = m_LocalAuthoritativeNetworkState.PositionY;
}

if (m_LocalAuthoritativeNetworkState.HasPositionZ)
{
currentPosition.z = m_LocalAuthoritativeNetworkState.PositionZ;
newTargetPosition.z = m_LocalAuthoritativeNetworkState.PositionZ;
}
UpdatePositionInterpolator(currentPosition, sentTime);
UpdatePositionInterpolator(newTargetPosition, sentTime);
m_TargetPosition = newTargetPosition;
}
}

if (m_LocalAuthoritativeNetworkState.HasScaleChange)
{
var currentScale = transform.localScale;
var currentScale = m_TargetScale;
if (UseHalfFloatPrecision)
{
for (int i = 0; i < 3; i++)
Expand Down Expand Up @@ -2207,6 +2213,7 @@ private void UpdateState(NetworkTransformState oldState, NetworkTransformState n
currentScale.z = m_LocalAuthoritativeNetworkState.ScaleZ;
}
}
m_TargetScale = currentScale;
m_ScaleInterpolator.AddMeasurement(currentScale, sentTime);
}

Expand All @@ -2221,7 +2228,9 @@ private void UpdateState(NetworkTransformState oldState, NetworkTransformState n
}
else
{
currentEulerAngles = m_TargetRotation;
// Adjust based on which axis changed
// (both half precision and full precision apply Eulers to the RotAngle properties when reading the update)
if (m_LocalAuthoritativeNetworkState.HasRotAngleX)
{
currentEulerAngles.x = m_LocalAuthoritativeNetworkState.RotAngleX;
Expand All @@ -2236,6 +2245,7 @@ private void UpdateState(NetworkTransformState oldState, NetworkTransformState n
{
currentEulerAngles.z = m_LocalAuthoritativeNetworkState.RotAngleZ;
}
m_TargetRotation = currentEulerAngles;
currentRotation.eulerAngles = currentEulerAngles;
}

Expand Down Expand Up @@ -2489,8 +2499,11 @@ protected void Initialize()

ResetInterpolatedStateToCurrentAuthoritativeState();
m_CurrentPosition = currentPosition;
m_TargetPosition = currentPosition;
m_CurrentScale = transform.localScale;
m_TargetScale = transform.localScale;
m_CurrentRotation = currentRotation;
m_TargetRotation = currentRotation.eulerAngles;

}

Expand Down Expand Up @@ -2649,7 +2662,7 @@ protected virtual void Update()
var serverTime = NetworkManager.ServerTime;
var cachedDeltaTime = NetworkManager.RealTimeProvider.DeltaTime;
var cachedServerTime = serverTime.Time;
// TODO: Investigate Further

// With owner authoritative mode, non-authority clients can lag behind
// by more than 1 tick period of time. The current "solution" for now
// is to make their cachedRenderTime run 2 ticks behind.
Expand Down
6 changes: 5 additions & 1 deletion Editor/CodeGen/CodeGenHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static uint Hash(this MethodDefinition methodDefinition)

public static bool IsSubclassOf(this TypeDefinition typeDefinition, string classTypeFullName)
{
if (!typeDefinition.IsClass)
if (typeDefinition == null || !typeDefinition.IsClass)
{
return false;
}
Expand Down Expand Up @@ -154,6 +154,10 @@ public static MethodReference MakeGeneric(this MethodReference self, params Type

public static bool IsSubclassOf(this TypeReference typeReference, TypeReference baseClass)
{
if (typeReference == null)
{
return false;
}
var type = typeReference.Resolve();
if (type?.BaseType == null || type.BaseType.Name == nameof(Object))
{
Expand Down
30 changes: 18 additions & 12 deletions Editor/CodeGen/NetworkBehaviourILPP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ private void CreateNetworkVariableTypeInitializers(AssemblyDefinition assembly)
#endif
private MethodReference m_NetworkVariableSerializationTypes_InitializeEqualityChecker_ManagedClassEquals_MethodRef;

private MethodReference m_RuntimeInitializeOnLoadAttribute_Ctor;

private MethodReference m_ExceptionCtorMethodReference;
private MethodReference m_List_NetworkVariableBase_Add;

Expand Down Expand Up @@ -509,6 +511,8 @@ private bool ImportReferences(ModuleDefinition moduleDefinition)
}
}

m_RuntimeInitializeOnLoadAttribute_Ctor = moduleDefinition.ImportReference(typeof(RuntimeInitializeOnLoadMethodAttribute).GetConstructor(new Type[] { }));

TypeDefinition networkManagerTypeDef = null;
TypeDefinition networkBehaviourTypeDef = null;
TypeDefinition networkVariableBaseTypeDef = null;
Expand Down Expand Up @@ -1200,19 +1204,14 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] ass

if (rpcHandlers.Count > 0 || rpcNames.Count > 0)
{
var staticCtorMethodDef = typeDefinition.GetStaticConstructor();
if (staticCtorMethodDef == null)
{
staticCtorMethodDef = new MethodDefinition(
".cctor", // Static Constructor (constant-constructor)
MethodAttributes.HideBySig |
MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName |
var staticCtorMethodDef = new MethodDefinition(
$"InitializeRPCS_{typeDefinition.Name}",
MethodAttributes.Assembly |
MethodAttributes.Static,
typeDefinition.Module.TypeSystem.Void);
staticCtorMethodDef.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
typeDefinition.Methods.Add(staticCtorMethodDef);
}
staticCtorMethodDef.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
staticCtorMethodDef.CustomAttributes.Add(new CustomAttribute(m_RuntimeInitializeOnLoadAttribute_Ctor));
typeDefinition.Methods.Add(staticCtorMethodDef);

var instructions = new List<Instruction>();
var processor = staticCtorMethodDef.Body.GetILProcessor();
Expand Down Expand Up @@ -1254,7 +1253,8 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] ass
baseGetTypeNameMethod.ReturnType)
{
ImplAttributes = baseGetTypeNameMethod.ImplAttributes,
SemanticsAttributes = baseGetTypeNameMethod.SemanticsAttributes
SemanticsAttributes = baseGetTypeNameMethod.SemanticsAttributes,
IsFamilyOrAssembly = true
};

var processor = newGetTypeNameMethod.Body.GetILProcessor();
Expand Down Expand Up @@ -2225,6 +2225,12 @@ private void GenerateVariableInitialization(TypeDefinition type)
}
field = new FieldReference(fieldDefinition.Name, fieldDefinition.FieldType, genericType);
}

if (field.FieldType.Resolve() == null)
{
continue;
}

if (!field.FieldType.IsArray && !field.FieldType.Resolve().IsArray && field.FieldType.IsSubclassOf(m_NetworkVariableBase_TypeRef))
{
// if({variable} == null) {
Expand Down
15 changes: 14 additions & 1 deletion Editor/CodeGen/RuntimeAccessModifiersILPP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ private void ProcessNetworkManager(TypeDefinition typeDefinition, string[] assem
fieldDefinition.IsPublic = true;
}
}

foreach (var nestedTypeDefinition in typeDefinition.NestedTypes)
{
if (nestedTypeDefinition.Name == nameof(NetworkManager.RpcReceiveHandler))
{
nestedTypeDefinition.IsNestedPublic = true;
}
}
}

private void ProcessNetworkBehaviour(TypeDefinition typeDefinition)
Expand All @@ -114,7 +122,7 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition)
{
if (fieldDefinition.Name == nameof(NetworkBehaviour.__rpc_exec_stage) || fieldDefinition.Name == nameof(NetworkBehaviour.NetworkVariableFields))
{
fieldDefinition.IsFamily = true;
fieldDefinition.IsFamilyOrAssembly = true;
}
}

Expand All @@ -130,6 +138,11 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition)
{
methodDefinition.IsFamily = true;
}

if (methodDefinition.Name == nameof(NetworkBehaviour.__getTypeName))
{
methodDefinition.IsFamilyOrAssembly = true;
}
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions Runtime/Connection/NetworkClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,11 @@ public class NetworkClient
/// <summary>
/// The ClientId of the NetworkClient
/// </summary>
// TODO-2023-Q2: Determine if we want to make this property a public get and internal/private set
// There is no reason for a user to want to set this, but this will fail the package-validation-suite
public ulong ClientId;

/// <summary>
/// The PlayerObject of the Client
/// </summary>
// TODO-2023-Q2: Determine if we want to make this property a public get and internal/private set
// There is no reason for a user to want to set this, but this will fail the package-validation-suite
public NetworkObject PlayerObject;

/// <summary>
Expand Down
22 changes: 11 additions & 11 deletions Runtime/Connection/NetworkConnectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ namespace Unity.Netcode
/// - Processing <see cref="NetworkEvent"/>s.
/// - Client Disconnection
/// </summary>
// TODO 2023-Q2: Discuss what kind of public API exposure we want for this
public sealed class NetworkConnectionManager
{
#if DEVELOPMENT_BUILD || UNITY_EDITOR
Expand Down Expand Up @@ -628,6 +627,8 @@ internal void HandleConnectionApproval(ulong ownerClientId, NetworkManager.Conne
};
if (!NetworkManager.NetworkConfig.EnableSceneManagement)
{
// Update the observed spawned NetworkObjects for the newly connected player when scene management is disabled
NetworkManager.SpawnManager.UpdateObservedNetworkObjects(ownerClientId);
if (NetworkManager.SpawnManager.SpawnedObjectsList.Count != 0)
{
message.SpawnedObjectsList = NetworkManager.SpawnManager.SpawnedObjectsList;
Expand All @@ -651,12 +652,13 @@ internal void HandleConnectionApproval(ulong ownerClientId, NetworkManager.Conne
SendMessage(ref message, NetworkDelivery.ReliableFragmentedSequenced, ownerClientId);
message.MessageVersions.Dispose();

// If scene management is enabled, then let NetworkSceneManager handle the initial scene and NetworkObject synchronization
// If scene management is disabled, then we are done and notify the local host-server the client is connected
if (!NetworkManager.NetworkConfig.EnableSceneManagement)
{
NetworkManager.ConnectedClients[ownerClientId].IsConnected = true;
InvokeOnClientConnectedCallback(ownerClientId);
}
else
else // Otherwise, let NetworkSceneManager handle the initial scene and NetworkObject synchronization
{
NetworkManager.SceneManager.SynchronizeNetworkObjects(ownerClientId);
}
Expand All @@ -665,6 +667,7 @@ internal void HandleConnectionApproval(ulong ownerClientId, NetworkManager.Conne
{
LocalClient = client;
NetworkManager.SpawnManager.UpdateObservedNetworkObjects(ownerClientId);
LocalClient.IsConnected = true;
}

if (!response.CreatePlayerObject || (response.PlayerPrefabHash == null && NetworkManager.NetworkConfig.PlayerPrefab == null))
Expand Down Expand Up @@ -730,12 +733,10 @@ internal void ApprovedPlayerSpawn(ulong clientId, uint playerPrefabHash)
internal NetworkClient AddClient(ulong clientId)
{
var networkClient = LocalClient;
if (clientId != NetworkManager.ServerClientId)
{
networkClient = new NetworkClient();
networkClient.SetRole(isServer: false, isClient: true, NetworkManager);
networkClient.ClientId = clientId;
}

networkClient = new NetworkClient();
networkClient.SetRole(clientId == NetworkManager.ServerClientId, isClient: true, NetworkManager);
networkClient.ClientId = clientId;

ConnectedClients.Add(clientId, networkClient);
ConnectedClientsList.Add(networkClient);
Expand Down Expand Up @@ -798,8 +799,7 @@ internal void OnClientDisconnectFromServer(ulong clientId)
}
else
{
// Handle changing ownership and prefab handlers
// TODO-2023: Look into whether in-scene placed NetworkObjects could be destroyed if ownership changes to a client
// Handle changing ownership and prefab handlers
for (int i = clientOwnedObjects.Count - 1; i >= 0; i--)
{
var ownedObject = clientOwnedObjects[i];
Expand Down
4 changes: 0 additions & 4 deletions Runtime/Core/NetworkBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ internal enum __RpcExecStage
Server = 1,
Client = 2
}


// NetworkBehaviourILPP will override this in derived classes to return the name of the concrete type
internal virtual string __getTypeName() => nameof(NetworkBehaviour);

Expand Down Expand Up @@ -98,7 +96,6 @@ internal void __endSendServerRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
}

bufferWriter.Dispose();

#if DEVELOPMENT_BUILD || UNITY_EDITOR
if (NetworkManager.__rpc_name_table.TryGetValue(rpcMethodId, out var rpcMethodName))
{
Expand Down Expand Up @@ -230,7 +227,6 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
}

bufferWriter.Dispose();

#if DEVELOPMENT_BUILD || UNITY_EDITOR
if (NetworkManager.__rpc_name_table.TryGetValue(rpcMethodId, out var rpcMethodName))
{
Expand Down
2 changes: 1 addition & 1 deletion Runtime/Core/NetworkBehaviourUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ internal void Shutdown()
m_NetworkManager.NetworkTickSystem.Tick -= NetworkBehaviourUpdater_Tick;
}

// TODO 2023-Q2: Order of operations requires NetworkVariable updates first then showing NetworkObjects
// Order of operations requires NetworkVariable updates first then showing NetworkObjects
private void NetworkBehaviourUpdater_Tick()
{
// First update NetworkVariables
Expand Down
Loading

0 comments on commit 0581a42

Please sign in to comment.