The dynamically spawned network object in Host is not spawned(appeared) in Client.

Hello
I am working on PvP for a 2D game.
All things are working on Unity Editor which means that 2 spawned network objects in Host are also spawned in Client.
But it is not working in APK build in Android Device.
I attached some code block and video.

— Spawn object in Host(only in Host)

public PvPCruiser CreateCruiser(PvPCruiser cruiserPrefab, ulong ClientNetworkId, float x)
{
PvPCruiser cruiser = Object.Instantiate(cruiserPrefab, new Vector3(x, 0f, 0f), Quaternion.identity);
cruiser.GetComponent().SpawnWithOwnership(ClientNetworkId);
cruiser.GetComponent().DontDestroyWithOwner = false;
cruiser.StaticInitialise(_commonStrings);
return cruiser;
}

So, the object is spawned in Host and it is reflected in Client when I play it on Unity Editor

But it is not working well in android build in Android Device.
What i mean : the object is only spawned in Host , it is not reflected in client in Android Device.

I will attach 2 videos to show them.(Left is Host, Right is Client in videos)

bandicam 2023-09-13 16-33-07-790.mp4 - Google Drive (Unity Editor)
bandicam 2023-09-13 16-37-57-141.mp4 - Google Drive (Android Emulator)

I want to find a clue to resolve it as soon as possible.

Further observations from me, a team member of OP:

First of all, it seems that the problem is not just with object instantiation but rather with the network synchronization on Android builds specifically. When running the game in the Unity Editor, network communication works flawlessly: objects are spawned on both the Host and Client sides and can interact with each other without any hiccups.

Observations:

  • Client-Host Communication: During my debugging, I found out that the ClientNetworkId is received correctly by the Host but is not reflected on the Client side when running on an Android device.

  • Logcat: I went through the Android Logcat and found no specific errors related to networking or object instantiation, which makes this all the more puzzling.

  • Debugging: Further debug logs indicated that the CreateCruiser function is being called and executed without any errors on the Android build; however, the spawned object simply does not appear on the Client side.

  • Network Permissions: I double-checked my AndroidManifest.xml, and all the required permissions for networking are set.

Additional Clues:
I tried bypassing the SpawnWithOwnership(ClientNetworkId) function and instead used a basic Spawn() function for testing. The object was spawned on both the Host and Client when running on an Android device, but obviously, I couldn’t control it properly due to lack of ownership.

This leads me to believe that the issue might be tied to the ownership settings or the SpawnWithOwnership() function specifically when running on Android.

I hope these additional observations help us zero in on the actual issue. If anyone else has encountered this problem and found a solution, your insights would be greatly appreciated.

Hello,
I have the same issue and I think that SpawnWithOwnership doesn’t work at all for clients, since several versions of Unity.
I tried with a windows build and in the editor. The object just doesn’t appear, while a simple Spawn works fine.

I was not very accurate. It doesn’t work when the owner is a client, not the host.

public async Task AddCapacity(int capacityToAdd)
{
for (int i = 0; i < capacityToAdd; ++i)
{
var item = await _itemFactory.CreateItem();
await Task.Delay(100);
_items.Push(item);
}
}

as you can see above codes, I add some delay to creating and spawning next networkobject to resolve the issue.

Oh, thanks for sharing this.
I don’t know if it is very safe though. If a player PC is slow or something.

The code seems fairly straightforward, instantiating a PvPBuildableWrapper object and setting it up for network synchronization with SpawnWithOwnership(clientID). However, the fact that the issue only appears on Android and not within the Unity Editor suggests that there may be a platform-specific issue or behavior that’s causing the problem.

Here are a few things you might want to consider checking:

  • Type Generics: Unity sometimes behaves differently with generic types on different platforms. Although not very likely, you might want to try using a non-generic version for testing purposes.
  • Object Activation: buildableWrapper.gameObject.SetActive(true); is called after SpawnWithOwnership. Sometimes, the order of operations matters. Consider setting it active before spawning with ownership to see if that has any effect.
  • Network Initialization: Ensure that the NetworkObject component is fully initialized before calling SpawnWithOwnership(clientID). Initialization delays could lead to unexpected behavior.
  • Logs and Debugging: Add more logging around the SpawnWithOwnership(clientID) call to ensure that clientID is what you expect and that the function is being called when and where you expect it.
  • Unity Version: Sometimes, these types of issues are Unity version-dependent. Make sure that you and your client are using versions of Unity and NGO that are known to be compatible.
  • Build Settings: Double-check if there are any build settings that might be affecting the Android build differently from the Editor build.

Here’s a slightly modified version of the function, with added logging for debugging purposes:

private TBuildable CreateBuildingBuildable<TBuildable>(
    PvPBuildableWrapper<TBuildable> buildableWrapperPrefab,
    IPvPFactoryProvider factoryProvider,
    ulong clientID) where TBuildable : class, IPvPBuilding
{
    PvPHelper.AssertIsNotNull(buildableWrapperPrefab, factoryProvider);
  
    // Debug log to check values
    Debug.Log($"ClientID: {clientID}");
  
    PvPBuildableWrapper<TBuildable> buildableWrapper = Object.Instantiate(buildableWrapperPrefab);
  
    buildableWrapper.gameObject.SetActive(true);  // Setting active before spawn
  
    // More debug logging
    Debug.Log("About to spawn with ownership...");
  
    buildableWrapper.GetComponent<NetworkObject>().SpawnWithOwnership(clientID);
  
    // Debug log to confirm spawn
    Debug.Log("Spawned with ownership");
  
    buildableWrapper.GetComponent<NetworkObject>().DontDestroyWithOwner = false;
    buildableWrapper.StaticInitialise(_commonStrings);
    buildableWrapper.Buildable.Initialise(factoryProvider);
  
    return buildableWrapper.Buildable;
}

Please try these and let me know if they resolve your issue or provide any additional context as to what the issue may be.

To add to what Brandon just posted yesterday:

Deferred Message (SpawnTimeout) Period:
With Android and/or any platform that could take a bit longer to load assets, you could be running into an issue with messages being received but not processed for a “yet to be instantiated/spawned” object. The default setting for deferred messages (i.e. messages received for a NetworkObject->NetworkBehaviour yet to be spawned/instantiated) is 1 second…if the associated NetworkObject (or NetworkBehaviour component) does not exist within that period of time then the message gets dropped.

You might try increasing the NetworkManager.NetworkConfig.SpawnTimeout value to like say 10 seconds (or some value you think is reasonable) and see if that helps.

Some other pointers:

  • When things seem to not work on mobile devices (especially Android), as a “sanity” check you might make a build with the “Project Settings->Player->Other Settings->Optimization->Managed Stripping Level” set to minimal to just make sure some critical method or the like is not being stripped away by accident (if you run into this issue you will want to read about preserving code using annotations)
  • Disabled NetworkBehaviours will not be considered “associated” with a NetworkObject if they are disabled when the NetworkObject is spawned (you can disable them after the NetworkObject is spawned as the NetworkObject will have already registered it…RPCs will still get invoked and NetworkVariables will still be updated if a NetworkBehaviour is disabled post-spawn).

Let me know if any of the above helps?