Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions com.unity.netcode.gameobjects/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Additional documentation and release notes are available at [Multiplayer Documen

### Added

- The `NetworkMetricsPipelineStage` for Unity Transport is now part of the public API. This allows using it in custom implementations of `INetworkStreamDriverConstructor` that want to maintain compatibility with the multiplayer tools package. (#3853)

### Changed

Expand All @@ -24,6 +25,7 @@ Additional documentation and release notes are available at [Multiplayer Documen

### Fixed

- Prevented a `NullReferenceException` in `UnityTransport` when using a custom `INetworkStreamDriverConstructor` that doesn't use all the default pipelines and the multiplayer tools package is installed. (#3853)
- Fixed an integer overflow that occurred when configuring a large disconnect timeout with Unity Transport. (#3810)

### Security
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ namespace Unity.Netcode.Transports.UTP
/// var settings = transport.GetDefaultNetworkSettings();
/// driver = NetworkDriver.Create(new IPCNetworkInterface(), settings);
///
/// driver.RegisterPipelineStage(new NetworkMetricsPipelineStage());
///
/// transport.GetDefaultPipelineConfigurations(
/// out var unreliableFragmentedPipelineStages,
/// out var unreliableSequencedFragmentedPipelineStages,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,32 @@

namespace Unity.Netcode.Transports.UTP
{
/// <summary>
/// A pipeline stage that tracks some internal metrics that are then used by the multiplayer
/// tools package. This should only be used when creating a custom <see cref="NetworkDriver"/>
/// with <see cref="INetworkStreamDriverConstructor"/> if compatibility with the multiplayer
/// tools package is desired. In that situation, this stage needs to be registered with the
/// constructed driver with <see cref="NetworkDriver.RegisterPipelineStage{T}"/>.
/// </summary>
[BurstCompile]
internal unsafe struct NetworkMetricsPipelineStage : INetworkPipelineStage
public unsafe struct NetworkMetricsPipelineStage : INetworkPipelineStage
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that due to this change you should bump package version in package.json to 2.9.0. But vetting test should verify this (will fail if you should bump it)

{
private static TransportFunctionPointer<NetworkPipelineStage.ReceiveDelegate> s_ReceiveFunction = new TransportFunctionPointer<NetworkPipelineStage.ReceiveDelegate>(Receive);
private static TransportFunctionPointer<NetworkPipelineStage.SendDelegate> s_SendFunction = new TransportFunctionPointer<NetworkPipelineStage.SendDelegate>(Send);
private static TransportFunctionPointer<NetworkPipelineStage.InitializeConnectionDelegate> s_InitializeConnectionFunction = new TransportFunctionPointer<NetworkPipelineStage.InitializeConnectionDelegate>(InitializeConnection);

/// <inheritdoc/>
public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer,
int staticInstanceBufferLength,
NetworkSettings settings)
{
return new NetworkPipelineStage(
s_ReceiveFunction,
s_SendFunction,
s_InitializeConnectionFunction,
new TransportFunctionPointer<NetworkPipelineStage.ReceiveDelegate>(Receive),
new TransportFunctionPointer<NetworkPipelineStage.SendDelegate>(Send),
new TransportFunctionPointer<NetworkPipelineStage.InitializeConnectionDelegate>(InitializeConnection),
ReceiveCapacity: 0,
SendCapacity: 0,
HeaderCapacity: 0,
SharedStateCapacity: UnsafeUtility.SizeOf<NetworkMetricsContext>());
}

/// <inheritdoc/>
public int StaticSize => 0;

[BurstCompile(DisableDirectCall = true)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1234,13 +1234,30 @@ private void ExtractNetworkMetricsFromPipeline(NetworkPipeline pipeline, Network
return;
}

//Don't need to dispose of the buffers, they are filled with data pointers.
m_Driver.GetPipelineBuffers(pipeline,
NetworkPipelineStageId.Get<NetworkMetricsPipelineStage>(),
networkConnection,
out _,
out _,
out var sharedBuffer);
var sharedBuffer = default(NativeArray<byte>);

try
{
// Don't need to dispose of the buffers, they are filled with data pointers.
m_Driver.GetPipelineBuffers(pipeline,
NetworkPipelineStageId.Get<NetworkMetricsPipelineStage>(),
networkConnection,
out _,
out _,
out sharedBuffer);
}
catch (InvalidOperationException)
{
// Can happen if using a custom driver that isn't configured with the metrics stage.
return;
}

// That InvalidOperationException above is only thrown in the editor. In runtime builds
// we instead get default return values when the pipeline stage is invalid.
if (sharedBuffer == default)
{
return;
}

unsafe
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using NUnit.Framework;
using Unity.Netcode.Transports.UTP;
using Unity.Networking.Transport;
using UnityEngine;
using UnityEngine.TestTools;

Expand Down Expand Up @@ -229,5 +230,46 @@ public void UnityTransport_HostnameValidation((string, bool) testCase)
transport.Shutdown();
}
#endif

private class IPCDriverConstructor : INetworkStreamDriverConstructor
{
public void CreateDriver(
UnityTransport transport,
out NetworkDriver driver,
out NetworkPipeline unreliableFragmentedPipeline,
out NetworkPipeline unreliableSequencedFragmentedPipeline,
out NetworkPipeline reliableSequencedPipeline)
{
var settings = transport.GetDefaultNetworkSettings();
driver = NetworkDriver.Create(new IPCNetworkInterface(), settings);

#if MULTIPLAYER_TOOLS
driver.RegisterPipelineStage(new NetworkMetricsPipelineStage());
#endif

transport.GetDefaultPipelineConfigurations(
out var unreliableFragmentedPipelineStages,
out var unreliableSequencedFragmentedPipelineStages,
out var reliableSequencedPipelineStages);

unreliableFragmentedPipeline = driver.CreatePipeline(unreliableFragmentedPipelineStages);
unreliableSequencedFragmentedPipeline = driver.CreatePipeline(unreliableSequencedFragmentedPipelineStages);
reliableSequencedPipeline = driver.CreatePipeline(reliableSequencedPipelineStages);
}
}

[Test]
public void UnityTransport_CustomDriverConstructorWithDefaultPipelines()
{
UnityTransport transport = new GameObject().AddComponent<UnityTransport>();
UnityTransport.s_DriverConstructor = new IPCDriverConstructor();
transport.Initialize();

Assert.True(transport.StartServer());

transport.Shutdown();

UnityTransport.s_DriverConstructor = null;
}
}
}
2 changes: 1 addition & 1 deletion com.unity.netcode.gameobjects/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.8.1",
"version": "2.9.0",
"unity": "6000.0",
"dependencies": {
"com.unity.nuget.mono-cecil": "1.11.4",
Expand Down