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.0.0-pre.8] - 2022-04-27

### Changed

- `unmanaged` structs are no longer universally accepted as RPC parameters because some structs (i.e., structs with pointers in them, such as `NativeList<T>`) can't be supported by the default memcpy struct serializer. Structs that are intended to be serialized across the network must add `INetworkSerializeByMemcpy` to the interface list (i.e., `struct Foo : INetworkSerializeByMemcpy`). This interface is empty and just serves to mark the struct as compatible with memcpy serialization. For external structs you can't edit, you can pass them to RPCs by wrapping them in `ForceNetworkSerializeByMemcpy<T>`. (#1901)

### Removed
- Removed `SIPTransport` (#1870)

- Removed `ClientNetworkTransform` from the package samples and moved to Boss Room's Utilities package which can be found [here](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs).

### Fixed

- Fixed `NetworkTransform` generating false positive rotation delta checks when rolling over between 0 and 360 degrees. (#1890)
- Fixed client throwing an exception if it has messages in the outbound queue when processing the `NetworkEvent.Disconnect` event and is using UTP. (#1884)
- Fixed issue during client synchronization if 'ValidateSceneBeforeLoading' returned false it would halt the client synchronization process resulting in a client that was approved but not synchronized or fully connected with the server. (#1883)
- Fixed an issue where UNetTransport.StartServer would return success even if the underlying transport failed to start (#854)
- Passing generic types to RPCs no longer causes a native crash (#1901)
- Fixed an issue where calling `Shutdown` on a `NetworkManager` that was already shut down would cause an immediate shutdown the next time it was started (basically the fix makes `Shutdown` idempotent). (#1877)
  • Loading branch information
Unity Technologies committed Apr 27, 2022
1 parent 60e2dab commit add668d
Show file tree
Hide file tree
Showing 119 changed files with 4,423 additions and 1,790 deletions.
29 changes: 25 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,40 @@ 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.0.0-pre.7] - 2022-04-01
## [1.0.0-pre.8] - 2022-04-27

### Added
### Changed

- `unmanaged` structs are no longer universally accepted as RPC parameters because some structs (i.e., structs with pointers in them, such as `NativeList<T>`) can't be supported by the default memcpy struct serializer. Structs that are intended to be serialized across the network must add `INetworkSerializeByMemcpy` to the interface list (i.e., `struct Foo : INetworkSerializeByMemcpy`). This interface is empty and just serves to mark the struct as compatible with memcpy serialization. For external structs you can't edit, you can pass them to RPCs by wrapping them in `ForceNetworkSerializeByMemcpy<T>`. (#1901)

### Removed
- Removed `SIPTransport` (#1870)

- Removed `ClientNetworkTransform` from the package samples and moved to Boss Room's Utilities package which can be found [here](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs).

### Fixed

- Fixed `NetworkTransform` generating false positive rotation delta checks when rolling over between 0 and 360 degrees. (#1890)
- Fixed client throwing an exception if it has messages in the outbound queue when processing the `NetworkEvent.Disconnect` event and is using UTP. (#1884)
- Fixed issue during client synchronization if 'ValidateSceneBeforeLoading' returned false it would halt the client synchronization process resulting in a client that was approved but not synchronized or fully connected with the server. (#1883)
- Fixed an issue where UNetTransport.StartServer would return success even if the underlying transport failed to start (#854)
- Passing generic types to RPCs no longer causes a native crash (#1901)
- Fixed an issue where calling `Shutdown` on a `NetworkManager` that was already shut down would cause an immediate shutdown the next time it was started (basically the fix makes `Shutdown` idempotent). (#1877)

## [1.0.0-pre.7] - 2022-04-06

### Added
- Added editor only check prior to entering into play mode if the currently open and active scene is in the build list and if not displays a dialog box asking the user if they would like to automatically add it prior to entering into play mode. (#1828)
- Added `UnityTransport` implementation and `com.unity.transport` package dependency (#1823)
- Added `NetworkVariableWritePermission` to `NetworkVariableBase` and implemented `Owner` client writable netvars. (#1762)
- `UnityTransport` settings can now be set programmatically. (#1845)
- `FastBufferWriter` and Reader IsInitialized property. (#1859)
- Prefabs can now be added to the network at **runtime** (i.e., from an addressable asset). If `ForceSamePrefabs` is false, this can happen after a connection has been formed. (#1882)
- When `ForceSamePrefabs` is false, a configurable delay (default 1 second, configurable via `NetworkConfig.SpawnTimeout`) has been introduced to gracefully handle race conditions where a spawn call has been received for an object whose prefab is still being loaded. (#1882)

### Changed

- Changed `NetcodeIntegrationTestHelpers` to use `UnityTransport` (#1870)
- Updated `UnityTransport` dependency on `com.unity.transport` to 1.0.0 (#1849)

### Removed
Expand All @@ -27,6 +49,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
- Removed `com.unity.collections` dependency from the package (#1849)

### Fixed

- Fixed in-scene placed NetworkObjects not being found/ignored after a client disconnects and then reconnects. (#1850)
- Fixed issue where `UnityTransport` send queues were not flushed when calling `DisconnectLocalClient` or `DisconnectRemoteClient`. (#1847)
- Fixed NetworkBehaviour dependency verification check for an existing NetworkObject not searching from root parent transform relative GameObject. (#1841)
Expand All @@ -49,8 +72,6 @@ Additional documentation and release notes are available at [Multiplayer Documen
- NetworkAnimator now properly synchrhonizes all animation layers as well as runtime-adjusted weighting between them (#1765)
- Added first set of tests for NetworkAnimator - parameter syncing, trigger set / reset, override network animator (#1735)

### Changed

### Fixed
- Fixed an issue where sometimes the first client to connect to the server could see messages from the server as coming from itself. (#1683)
- Fixed an issue where clients seemed to be able to send messages to ClientId 1, but these messages would actually still go to the server (id 0) instead of that client. (#1683)
Expand Down
35 changes: 26 additions & 9 deletions Components/Interpolator/BufferedLinearInterpolator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@

namespace Unity.Netcode
{

/// <summary>
/// Solves for incoming values that are jittered
/// Partially solves for message loss. Unclamped lerping helps hide this, but not completely
/// </summary>
/// <typeparam name="T"></typeparam>
internal abstract class BufferedLinearInterpolator<T> where T : struct
public abstract class BufferedLinearInterpolator<T> where T : struct
{
private struct BufferedItem
{
Expand All @@ -24,6 +22,10 @@ public BufferedItem(T item, double timeSent)
}
}

/// <summary>
/// There’s two factors affecting interpolation: buffering (set in NetworkManager’s NetworkTimeSystem) and interpolation time, which is the amount of time it’ll take to reach the target. This is to affect the second one.
/// </summary>
public float MaximumInterpolationTime = 0.1f;

private const double k_SmallValue = 9.999999439624929E-11; // copied from Vector3's equal operator

Expand Down Expand Up @@ -69,13 +71,19 @@ public BufferedItem(T item, double timeSent)

private bool InvalidState => m_Buffer.Count == 0 && m_LifetimeConsumedCount == 0;

/// <summary>
/// Resets Interpolator to initial state
/// </summary>
public void Clear()
{
m_Buffer.Clear();
m_EndTimeConsumed = 0.0d;
m_StartTimeConsumed = 0.0d;
}

/// <summary>
/// Teleports current interpolation value to targetValue.
/// </summary>
public void ResetTo(T targetValue, double serverTime)
{
m_LifetimeConsumedCount = 1;
Expand All @@ -89,7 +97,6 @@ public void ResetTo(T targetValue, double serverTime)
Update(0, serverTime, serverTime);
}


// todo if I have value 1, 2, 3 and I'm treating 1 to 3, I shouldn't interpolate between 1 and 3, I should interpolate from 1 to 2, then from 2 to 3 to get the best path
private void TryConsumeFromBuffer(double renderTime, double serverTime)
{
Expand Down Expand Up @@ -205,14 +212,16 @@ public T Update(float deltaTime, double renderTime, double serverTime)
}

var target = InterpolateUnclamped(m_InterpStartValue, m_InterpEndValue, t);
float maxInterpTime = 0.1f;
m_CurrentInterpValue = Interpolate(m_CurrentInterpValue, target, deltaTime / maxInterpTime); // second interpolate to smooth out extrapolation jumps
m_CurrentInterpValue = Interpolate(m_CurrentInterpValue, target, deltaTime / MaximumInterpolationTime); // second interpolate to smooth out extrapolation jumps
}

m_NbItemsReceivedThisFrame = 0;
return m_CurrentInterpValue;
}

/// <summary>
/// Add measurements to be used during interpolation. These will be buffered before being made available to be displayed as "latest value".
/// </summary>
public void AddMeasurement(T newMeasurement, double sentTime)
{
m_NbItemsReceivedThisFrame++;
Expand All @@ -239,17 +248,25 @@ public void AddMeasurement(T newMeasurement, double sentTime)
}
}

/// <summary>
/// Gets latest value from the interpolator. This is updated every update as time goes by.
/// </summary>
public T GetInterpolatedValue()
{
return m_CurrentInterpValue;
}

/// <summary>
/// Method to override and adapted to the generic type. This assumes interpolation for that value will be clamped.
/// </summary>
protected abstract T Interpolate(T start, T end, float time);
/// <summary>
/// Method to override and adapted to the generic type. This assumes interpolation for that value will not be clamped.
/// </summary>
protected abstract T InterpolateUnclamped(T start, T end, float time);
}


internal class BufferedLinearInterpolatorFloat : BufferedLinearInterpolator<float>
public class BufferedLinearInterpolatorFloat : BufferedLinearInterpolator<float>
{
protected override float InterpolateUnclamped(float start, float end, float time)
{
Expand All @@ -262,7 +279,7 @@ protected override float Interpolate(float start, float end, float time)
}
}

internal class BufferedLinearInterpolatorQuaternion : BufferedLinearInterpolator<Quaternion>
public class BufferedLinearInterpolatorQuaternion : BufferedLinearInterpolator<Quaternion>
{
protected override Quaternion InterpolateUnclamped(Quaternion start, Quaternion end, float time)
{
Expand Down
30 changes: 15 additions & 15 deletions Components/NetworkAnimator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ public class NetworkAnimator : NetworkBehaviour
internal struct AnimationMessage : INetworkSerializable
{
// state hash per layer. if non-zero, then Play() this animation, skipping transitions
public int StateHash;
public float NormalizedTime;
public int Layer;
public float Weight;
public byte[] Parameters;
internal int StateHash;
internal float NormalizedTime;
internal int Layer;
internal float Weight;
internal byte[] Parameters;

public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
Expand All @@ -33,8 +33,8 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade

internal struct AnimationTriggerMessage : INetworkSerializable
{
public int Hash;
public bool Reset;
internal int Hash;
internal bool Reset;

public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
Expand All @@ -57,29 +57,29 @@ public Animator Animator
private bool m_SendMessagesAllowed = false;

// Animators only support up to 32 params
public static int K_MaxAnimationParams = 32;
private const int k_MaxAnimationParams = 32;

private int[] m_TransitionHash;
private int[] m_AnimationHash;
private float[] m_LayerWeights;

private unsafe struct AnimatorParamCache
{
public int Hash;
public int Type;
public fixed byte Value[4]; // this is a max size of 4 bytes
internal int Hash;
internal int Type;
internal fixed byte Value[4]; // this is a max size of 4 bytes
}

// 128 bytes per Animator
private FastBufferWriter m_ParameterWriter = new FastBufferWriter(K_MaxAnimationParams * sizeof(float), Allocator.Persistent);
private FastBufferWriter m_ParameterWriter = new FastBufferWriter(k_MaxAnimationParams * sizeof(float), Allocator.Persistent);
private NativeArray<AnimatorParamCache> m_CachedAnimatorParameters;

// We cache these values because UnsafeUtility.EnumToInt uses direct IL that allows a non-boxing conversion
private struct AnimationParamEnumWrapper
{
public static readonly int AnimatorControllerParameterInt;
public static readonly int AnimatorControllerParameterFloat;
public static readonly int AnimatorControllerParameterBool;
internal static readonly int AnimatorControllerParameterInt;
internal static readonly int AnimatorControllerParameterFloat;
internal static readonly int AnimatorControllerParameterBool;

static AnimationParamEnumWrapper()
{
Expand Down
92 changes: 56 additions & 36 deletions Components/NetworkRigidbody.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,77 +5,97 @@ namespace Unity.Netcode.Components
{
/// <summary>
/// NetworkRigidbody allows for the use of <see cref="Rigidbody"/> on network objects. By controlling the kinematic
/// mode of the rigidbody and disabling it on all peers but the authoritative one.
/// mode of the <see cref="Rigidbody"/> and disabling it on all peers but the authoritative one.
/// </summary>
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(NetworkTransform))]
public class NetworkRigidbody : NetworkBehaviour
{
/// <summary>
/// Determines if we are server (true) or owner (false) authoritative
/// </summary>
private bool m_IsServerAuthoritative;

private Rigidbody m_Rigidbody;
private NetworkTransform m_NetworkTransform;

private bool m_OriginalKinematic;
private RigidbodyInterpolation m_OriginalInterpolation;

// Used to cache the authority state of this rigidbody during the last frame
// Used to cache the authority state of this Rigidbody during the last frame
private bool m_IsAuthority;

/// <summary>
/// Gets a bool value indicating whether this <see cref="NetworkRigidbody"/> on this peer currently holds authority.
/// </summary>
private bool HasAuthority => m_NetworkTransform.CanCommitToTransform;

private void Awake()
{
m_Rigidbody = GetComponent<Rigidbody>();
m_NetworkTransform = GetComponent<NetworkTransform>();
m_IsServerAuthoritative = m_NetworkTransform.IsServerAuthoritative();

m_Rigidbody = GetComponent<Rigidbody>();
m_OriginalInterpolation = m_Rigidbody.interpolation;

// Set interpolation to none if NetworkTransform is handling interpolation, otherwise it sets it to the original value
m_Rigidbody.interpolation = m_NetworkTransform.Interpolate ? RigidbodyInterpolation.None : m_OriginalInterpolation;

// Turn off physics for the rigid body until spawned, otherwise
// clients can run fixed update before the first full
// NetworkTransform update
m_Rigidbody.isKinematic = true;
}

/// <summary>
/// For owner authoritative (i.e. ClientNetworkTransform)
/// we adjust our authority when we gain ownership
/// </summary>
public override void OnGainedOwnership()
{
UpdateOwnershipAuthority();
}

private void FixedUpdate()
/// <summary>
/// For owner authoritative(i.e. ClientNetworkTransform)
/// we adjust our authority when we have lost ownership
/// </summary>
public override void OnLostOwnership()
{
if (NetworkManager.IsListening)
{
if (HasAuthority != m_IsAuthority)
{
m_IsAuthority = HasAuthority;
UpdateRigidbodyKinematicMode();
}
}
UpdateOwnershipAuthority();
}

// Puts the rigidbody in a kinematic non-interpolated mode on everyone but the server.
private void UpdateRigidbodyKinematicMode()
/// <summary>
/// Sets the authority differently depending upon
/// whether it is server or owner authoritative
/// </summary>
private void UpdateOwnershipAuthority()
{
if (m_IsAuthority == false)
if (m_IsServerAuthoritative)
{
m_OriginalKinematic = m_Rigidbody.isKinematic;
m_Rigidbody.isKinematic = true;

m_OriginalInterpolation = m_Rigidbody.interpolation;
// Set interpolation to none, the NetworkTransform component interpolates the position of the object.
m_Rigidbody.interpolation = RigidbodyInterpolation.None;
m_IsAuthority = NetworkManager.IsServer;
}
else
{
// Resets the rigidbody back to it's non replication only state. Happens on shutdown and when authority is lost
m_Rigidbody.isKinematic = m_OriginalKinematic;
m_Rigidbody.interpolation = m_OriginalInterpolation;
m_IsAuthority = IsOwner;
}

// If you have authority then you are not kinematic
m_Rigidbody.isKinematic = !m_IsAuthority;

// Set interpolation of the Rigidbody based on authority
// With authority: let local transform handle interpolation
// Without authority: let the NetworkTransform handle interpolation
m_Rigidbody.interpolation = m_IsAuthority ? m_OriginalInterpolation : RigidbodyInterpolation.None;
}

/// <inheritdoc />
public override void OnNetworkSpawn()
{
m_IsAuthority = HasAuthority;
m_OriginalKinematic = m_Rigidbody.isKinematic;
m_OriginalInterpolation = m_Rigidbody.interpolation;
UpdateRigidbodyKinematicMode();
UpdateOwnershipAuthority();
}

/// <inheritdoc />
public override void OnNetworkDespawn()
{
UpdateRigidbodyKinematicMode();
m_Rigidbody.interpolation = m_OriginalInterpolation;
// Turn off physics for the rigid body until spawned, otherwise
// non-owners can run fixed updates before the first full
// NetworkTransform update and physics will be applied (i.e. gravity, etc)
m_Rigidbody.isKinematic = true;
}
}
}
Expand Down
Loading

0 comments on commit add668d

Please sign in to comment.