-
-
Notifications
You must be signed in to change notification settings - Fork 201
Description
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
- Verified
NetworkTrafficStatistics.EnableModeis set toDisabledon the StatisticsManager - Confirmed the issue only occurs when Inspector is in Debug mode
- Traced the stack to identify the null reference location
- Identified that
_serverTraffic/_clientTrafficare 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
- Open a project with FishNet 4.6.18
- Create or use any NetworkBehaviour with
[Replicate]and[Reconcile]prediction methods (FishNet's prediction samples would work) - Enter Play mode as Host (server + client)
- Spawn the predicted NetworkObject
- In the Inspector window, click the three-dot menu (⋮) in the top-right
- Select "Debug" to switch to Debug Inspector mode
- Click on the spawned NetworkObject in the Hierarchy
- 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.EnableModeset toDisabled - The issue appears to be an Editor-only problem triggered by reflection-based field access
Contact Discord: korzewarrior