Skip to content

NullReferenceException in NetworkTrafficStatistics with Debug Inspector #1000

@korzewarrior

Description

@korzewarrior

NullReferenceException in NetworkTrafficStatistics with Debug Inspector

Environment

  • Unity Version: 6.3 LTS
  • Fish-Networking Version: 4.6.18
  • Platform: Windows 11

Troubleshooting Steps Already Taken

  1. Verified NetworkTrafficStatistics.EnableMode is set to Disabled on the StatisticsManager
  2. Confirmed the issue only occurs when Inspector is in Debug mode
  3. Traced the stack to identify the null reference location
  4. Identified that _serverTraffic / _clientTraffic are null when accessed

Description

When the Unity Inspector is switched to Debug mode and a NetworkObject with prediction ([Replicate]/[Reconcile] methods) is selected in the Hierarchy, a NullReferenceException is thrown repeatedly in NetworkTrafficStatistics.AddInboundPacketIdData().

The error occurs every network tick, flooding the console and breaking gameplay until Play mode is stopped. This happens even when NetworkTrafficStatistics.EnableMode is set to Disabled.


Replication Steps

  1. Open a project with FishNet 4.6.18
  2. Create or use any NetworkBehaviour with [Replicate] and [Reconcile] prediction methods (FishNet's prediction samples would work)
  3. Enter Play mode as Host (server + client)
  4. Spawn the predicted NetworkObject
  5. In the Inspector window, click the three-dot menu (⋮) in the top-right
  6. Select "Debug" to switch to Debug Inspector mode
  7. Click on the spawned NetworkObject in the Hierarchy
  8. Observe the NullReferenceException spam in the Console

Expected Behavior

Selecting a NetworkObject in Debug Inspector mode should not cause errors. The statistics tracking code should gracefully handle cases where internal traffic objects are not initialized.


Actual Behavior

The following exception is thrown every tick:

NullReferenceException: Object reference not set to an instance of an object
FishNet.Managing.Statistic.NetworkTrafficStatistics.AddInboundPacketIdData (FishNet.Transporting.PacketId typeSource, System.String details, System.Int32 bytes, UnityEngine.GameObject gameObject, System.Boolean asServer) (at Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficStatistics.cs:208)
FishNet.Object.NetworkBehaviour.Server_SendReconcileRpc[T] (System.UInt32 hash, T& lastReconcileData, T reconcileData, FishNet.Transporting.Channel channel) (at Assets/FishNet/Runtime/Object/NetworkBehaviour/NetworkBehaviour.Prediction.cs:458)
FishNet.Object.NetworkBehaviour.Reconcile_Server[T] (System.UInt32 methodHash, T& lastReconcileData, T data, FishNet.Transporting.Channel channel) (at Assets/FishNet/Runtime/Object/NetworkBehaviour/NetworkBehaviour.Prediction.cs:1287)
FishNet.Object.NetworkBehaviour.Reconcile_Current[T] (System.UInt32 hash, T& lastReconcileData, GameKit.Dependencies.Utilities.Types.RingBuffer`1[T] reconcilesHistory, T data, FishNet.Transporting.Channel channel) (at Assets/FishNet/Runtime/Object/NetworkBehaviour/NetworkBehaviour.Prediction.cs:1342)
PawnPrediction.PerformReconcile (PawnPrediction+ReconcileData rd, FishNet.Transporting.Channel channel) (at <generated>:0)
PawnPrediction.CreateReconcile () (at Assets/_Starboys/Scripts/Pawn/PawnPrediction.cs:319)
PawnPrediction.TimeManager_OnTick () (at Assets/_Starboys/Scripts/Pawn/PawnPrediction.cs:312)
FishNet.Managing.Timing.TimeManager.IncreaseTick () (at Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs:738)
FishNet.Managing.Timing.TimeManager.<TickUpdate>g__MethodLogic|113_0 () (at Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs:389)
FishNet.Managing.Timing.TimeManager.TickUpdate () (at Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs:377)
FishNet.Transporting.NetworkReaderLoop.Update () (at Assets/FishNet/Runtime/Transporting/NetworkReaderLoop.cs:29)

Root Cause Analysis

In NetworkTrafficStatistics.cs, the method AddInboundPacketIdData() (line 208) calls:

GetBidirectionalNetworkTraffic(asServer).InboundTraffic.AddPacketIdData(...)

Where GetBidirectionalNetworkTraffic() returns:

private BidirectionalNetworkTraffic GetBidirectionalNetworkTraffic(bool asServer) 
    => asServer ? _serverTraffic : _clientTraffic;

The fields _serverTraffic and _clientTraffic are only initialized in InitializeOnce_Internal(). When Unity's Debug Inspector uses reflection to serialize/access fields on the NetworkBehaviour, it can trigger the reconcile code path in a context where these traffic objects are null.

The existing null check in NetworkBehaviour.Prediction.cs:455:

if (_networkTrafficStatistics != null)

...passes because the NetworkTrafficStatistics object exists, but its internal _serverTraffic/_clientTraffic fields are null.


Suggested Fix

Add null guards in NetworkTrafficStatistics.cs before accessing traffic objects:

internal void AddInboundPacketIdData(PacketId typeSource, string details, int bytes, GameObject gameObject, bool asServer)
{
    if (bytes <= 0)
        return;

    var traffic = GetBidirectionalNetworkTraffic(asServer);
    if (traffic == null || traffic.InboundTraffic == null)
        return;

    traffic.InboundTraffic.AddPacketIdData(typeSource, details, (ulong)bytes, gameObject);
}

Apply the same pattern to:

  • AddOutboundPacketIdData()
  • AddInboundSocketData()
  • AddOutboundSocketData()

Additional Notes

  • Switching the Inspector back to Normal mode stops the errors, but gameplay may already be broken
  • This occurs even with StatisticsManager.NetworkTraffic.EnableMode set to Disabled
  • The issue appears to be an Editor-only problem triggered by reflection-based field access

Contact Discord: korzewarrior

Metadata

Metadata

Assignees

No one assigned

    Labels

    Waiting For InformationNot enough information has been supplied to resolve this issue.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions