NetworkTransform stops syncing after repeated respawns or ownership changes
Description
In Distributed Authority, NetworkTransform sometimes stops working after repeatedly respawning or changing ownership.
This issue occurs randomly, usually after 3–10 cycles of despawning, respawning, and updating ownership. When this happens, movement sync completely stops for that object.
During debugging, I discovered that on the session owner’s side, the Interpolate property of the affected NetworkTransform is being set to false, while it remains true on all other clients.
To fix this, I implemented a workaround:
- I periodically check all NetworkTransform components on the session owner’s client.
- If I find one where Interpolate is false, I temporarily transfer ownership of that NetworkTransform to the session owner.
- Then, I reset Interpolate to true.
- Finally, I restore the original ownership.
Here's the code I’m using to work around the problem. It periodically checks all NetworkTransform components and resets the Interpolate property when needed.
Important Note: If I try to reset the Interpolate property directly on its current owner, it has no effect — it only works after temporarily transferring ownership.
using System.Collections;
using Unity.Netcode;
using Unity.Netcode.Components;
using UnityEngine;
namespace Assets.Scripts
{
public class NetworkTransformFixer : MonoBehaviour
{
private Coroutine _fixerCoroutine;
private void Start()
{
_fixerCoroutine = StartCoroutine(PeriodicInterpolationCheck());
}
private void OnDestroy()
{
if (_fixerCoroutine != null)
{
StopCoroutine(_fixerCoroutine);
_fixerCoroutine = null;
}
}
private IEnumerator PeriodicInterpolationCheck()
{
while (true)
{
yield return new WaitForSeconds(1f);
FixNetworkTransformInterpolation();
}
}
private void FixNetworkTransformInterpolation()
{
if (!NetworkManager.Singleton.LocalClient.IsSessionOwner)
return;
var networkTransforms = FindObjectsByType<NetworkTransform>(FindObjectsSortMode.None);
// Check if any NetworkTransform has interpolation issues
foreach (var networkTransform in networkTransforms)
{
var originalOwner = networkTransform.OwnerClientId;
if (networkTransform.IsSpawned && !networkTransform.Interpolate)
{
networkTransform.NetworkObject.ChangeOwnership(NetworkManager.Singleton.LocalClientId);
networkTransform.Interpolate = true;
// Restore original ownership
networkTransform.NetworkObject.ChangeOwnership(originalOwner);
}
}
}
}
}
Environment
- Netcode Version: v2.5.0
- Netcode Topology: Distributed Authority
@nikajavakha
In Distributed Authority, NetworkTransform sometimes stops working after repeatedly respawning or changing ownership.
Can you provide the following additional details on this issue?
- Repeatedly respawning details
- What is being spawned
- Perhaps screenshots of the inspector view for this and/or details on what components this has on it?
- Is this an in-scene placed or dynamically spawned NetworkObject?
- The script that is spawning and despawning the NetworkObject
- The script related to the despawning:
- Are you completely disabling the root GameObject?
- If not, could you provide details on what happens to the de-spawned instance?
- Are you completely disabling the root GameObject?
- Any script that handles resetting the instance to its default settings (either prior to spawn and/or during despawn)
- The script related to the despawning:
- What is being spawned
- Repeatedly changing ownership details
- The time period between ownership changes.
- Are you repeatedly changing ownership in the same call-stack and/or same frame?
- Any additional details/script pertaining to what is triggering the change in ownership.
- The time period between ownership changes.
This issue occurs randomly, usually after 3–10 cycles of despawning, respawning, and updating ownership. When this happens, movement sync completely stops for that object.
This pertains to some of the additional details needed. What time frame constitutes a cycle? Is it player/client input driven (i.e. colliding into something) or is it timer based...etc.
During debugging, I discovered that on the session owner’s side, the Interpolate property of the affected NetworkTransform is being set to false, while it remains true on all other clients.
Is this true every time and does the session owner start as the authority of the spawned NetworkObject?
If you are using an object pool, could you provide details on the implementation? ( .i.e. Are you using the NetworkPrefabHandler approach? If not, could you describe how you are handling the recycling of the NetworkObjects?)
@NoelStephensUnity Here are the key details:
What's being spawned: NetworkPlayer prefabs with NetworkTransform components (transferable NetworkObjects)
The complete flow and what's happening:
When a game session ends, I need to reset everything back to lobby state. Here's the process:
- Pre-reload cleanup: Session owner takes ownership of all players from their original owners, then despawns them all
- Scene reload: I reload the scene using NetworkManager.SceneManager to completely reset the game state (positions, objects, etc.)
- Post-reload restoration: As each client finishes loading the scene, the session owner spawns a new player for that client and restores the original ownership
// When game ends - reset state by reloading scene
public void ReturnToLobby()
{
DespawnAllNetworkPlayers(); // Transfer all ownership to session owner + despawn
GameSceneNetworkSpawner.DespawnExistingObjects(); // Clean up other objects
LoadGameScene(); // Network scene reload to reset state
}
private void DespawnAllNetworkPlayers()
{
// Session owner takes ownership of every player before despawning
foreach (var networkPlayer in PlayerLookup.Instance.GetNetworkPlayers())
{
DespawnNetworkPlayer(networkPlayer);
}
}
private void DespawnNetworkPlayer(NetworkPlayer networkPlayer)
{
// Must transfer ownership to session owner first (only owner can despawn)
networkPlayer.NetworkObject.ChangeOwnership(NetworkManager.LocalClientId);
networkPlayer.NetworkObject.Despawn();
}
// After scene reload - spawn players as each client loads
private void OnSceneEvent(SceneEvent sceneEvent)
{
if (sceneEvent.SceneEventType == SceneEventType.LoadComplete)
{
SpawnPlayerForClient(sceneEvent.ClientId); // Create fresh player instance
}
}
private void SpawnPlayerForClient(ulong clientId)
{
// Spawn new player and give ownership back to original client
var networkPlayer = Instantiate(networkPlayerPrefab, spawnPoint.position, spawnPoint.rotation);
networkPlayer.NetworkObject.SpawnWithOwnership(clientId);
}
Key detail: This issue occurs most frequently after mid game sessions (5+ minutes) with multiple return-to-lobby cycles.
Interpolate issue: Only affects session owner's client - shows false while all other clients show true for the same NetworkTransform.
Why scene reload: Scene reload is the simplest way to reset all game state and return to clean lobby conditions.