Skip to content

IsOwner false on a NetworkBehaviour with 'NetworkObject that has IsOwner = True' #3210

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
MaybeKush opened this issue Jan 18, 2025 · 11 comments
Assignees
Labels
priority:medium This issue has medium priority and may take some time to be resolved stat:awaiting-response Awaiting response from author. This label should be added manually. stat:imported Status - Issue is tracked internally at Unity type:bug Bug Report

Comments

@MaybeKush
Copy link

MaybeKush commented Jan 18, 2025

Description

I have a class Fighter inheriting from NetworkBehaviour. Then a more specific class for the Fighter innheriting from Fighter. That class is attached to an object with NetworkObject component attached. I start server, spawn the object on Server (dynamically) with ownership = client (btw I spawn this new NetworkObject by Instantiating it under our Player default object, which is spawned by Network Manager under the Default Player Prefab field. Then after Instantiating it under that, only 1 line after I spawn it on the Network using its NetworkObject through the server). NetworkObject says IsOwner true, NetworkBehaviour script says IsOwner = false.

Reproduce Steps

Idk the steps exclusively. Though it could be related to Inheriting or how I instantiated it.

Actual Outcome

IsOwner is false on NetworkBehaviour but true on NetworkObject.

Expected Outcome

IsOwner should have been true in both NetworkObject and all NetworkBehaviours attached to it.

Screenshots

Image
Console is logging IsOwner from the NetworkBehaviour script

Environment

  • OS: Windows 10
  • Unity Version: 6000.0.24f1
  • Netcode Version: 2.2.0
  • Netcode Commit: Idk specifically, but the Package manager says released on December 16, 2024
@MaybeKush MaybeKush added stat:awaiting-triage Status - Awaiting triage from the Netcode team. type:bug Bug Report labels Jan 18, 2025
@EmandM
Copy link
Collaborator

EmandM commented Feb 7, 2025

What NetworkTopology are you using (Client-Server or Distributed Authority)? Could you post the code showing how you're instantiating the NetworkObject and the NetworkBehaviour?

@EmandM EmandM added stat:awaiting-response Awaiting response from author. This label should be added manually. and removed stat:awaiting-triage Status - Awaiting triage from the Netcode team. labels Feb 7, 2025
@MaybeKush
Copy link
Author

Sorry, didn't mean to close the issue lmao.

Image

This is the part where the network object is spawned. The OnNetworkSpawn method is on the "Player" object which is instantiated through the default player reference in NetworkManager which instantiates the "Player" object as soon as a client joins.

@michalChrobot michalChrobot removed the stat:awaiting-response Awaiting response from author. This label should be added manually. label Feb 10, 2025
@EmandM EmandM reopened this Feb 11, 2025
@EmandM
Copy link
Collaborator

EmandM commented Feb 11, 2025

Thank you for the code snippet. Do you mind explaining more about what behaviour you were expecting vs what was happening?

@MaybeKush
Copy link
Author

I am spawning the FIGHTER object with SpawnWithOwnership so I am expecting all the NetworkBehaviours attached on that FIGHTER object to also have isOwner = true for owners.

But as it turns out, only the NetworkObject component has isOwner = true for owner clients, and not the network behaviours.

I am currently working around this by using reference of the NetworkObject and checking NetworkObj.IsOwner.

@NoelStephensUnity
Copy link
Collaborator

NoelStephensUnity commented Feb 12, 2025

Hi @MaybeKush,

There might be some additional script I will need to better help you, but before we do that I have some recommendations based on the script segment you provided us:

  • Your script looks like it is Instantiating a NetworkObject and not the entire network prefab GameObject?
    • i.e. NetworkObject nObj = Instantiate(_fighters[1], transform);
      • My assumption is you are not getting any form of compilation error so _fighters[1] is an array of NetworkObjects?
    • This will not create a full network prefab instance.
    • You might try:
      • Instantiating the root GameObject of the network prefab asset.
      • Get the NetworkObject component of the instance.
        • Use this to invoke the Spawn method.
      • =or=
      • Use NetworkObject.InstantiateAndSpawn using the root GameObject of the network prefab asset.
  • I would recommend doing any spawning within the OnNetworkPostSpawn and not OnNetworkSpawn.
    • The reason being is that OnNetworkSpawn is while the NetworkObject is still in the middle of spawning (i.e. not all NetworkBehaviour components will have run through the spawn process yet) while OnNetworkPostSpawn assures that all NetworkBehaviour components have run through the spawn process (i.e. all spawned properties will be set on all of the associated NetworkBehaviour components).
  • Since you are spawning instances for each client connected, I would actually check against the NetworkBehaviour component's OwnerClientId relative to the default player prefab instance's OwnerClientId just to make sure you aren't checking for IsOwner on the Server/Host side when it is actually a newly connected client's player.
  • I noticed that you are passing in a direct NetworkObject as a parameter in InitializeOnTargetRpc. This will not work as you must use a NetworkObjectReference to do this (so you will want to make that adjustment too).

Once you have made those adjustments, let me know if you are still getting the same result.

@NoelStephensUnity NoelStephensUnity added the stat:awaiting-response Awaiting response from author. This label should be added manually. label Feb 12, 2025
@NoelStephensUnity NoelStephensUnity added type:support Questions or other support and removed type:bug Bug Report labels Feb 21, 2025
@kevincastejon
Copy link

@NoelStephensUnity
you say that instantiating the NetworkObject component of a NetworkPrefab "will not create a full network prefab instance".

Is that specific to netcode ?

Because with pure Unity, instantiating a gameobject, or one of its root component, will still instantiate the whole gameobject. Only the reference returned by the Instantiate method will change (gameobject vs the root component)

@kevincastejon
Copy link

kevincastejon commented Mar 15, 2025

@NoelStephensUnity could you please confirm or deny the above info ?
It is important info if there is netcode specific restriction on how to instantiate a network prefab.

@MaybeKush
Copy link
Author

@NoelStephensUnity Sorry for the late reply, must have missed the notification email.

Your script looks like it is Instantiating a NetworkObject and not the entire network prefab GameObject

This is a common instantiating method, if we want to use a specific component on an instantiated object, we can directly spawn the component of that type, instead of spawning gameobject then fetching the component on it. But I'll still try if spawning a gameobject makes any difference.

I would recommend doing any spawning within the OnNetworkPostSpawn and not OnNetworkSpawn

This, I can get behind. I'll try and return with the results

Passing NetworkObject into a RPC automatically turns it into a NetworkObjectReference. I think this is how they do in the official docs as well

@NoelStephensUnity
Copy link
Collaborator

@NoelStephensUnity Sorry for the late reply, must have missed the notification email.

Your script looks like it is Instantiating a NetworkObject and not the entire network prefab GameObject

This is a common instantiating method, if we want to use a specific component on an instantiated object, we can directly spawn the component of that type, instead of spawning gameobject then fetching the component on it. But I'll still try if spawning a gameobject makes any difference.

I would recommend doing any spawning within the OnNetworkPostSpawn and not OnNetworkSpawn

This, I can get behind. I'll try and return with the results

Passing NetworkObject into a RPC automatically turns it into a NetworkObjectReference. I think this is how they do in the official docs as well

@kevincastejon @MaybeKush

Your script looks like it is Instantiating a NetworkObject and not the entire network prefab GameObject

This was my mistake and I am not really sure why I added that comment other than I was thinking about "new" as opposed to Instantiate which creates a new instance of the GameObject and its components itself. >.<
That is definitely a perfectly valid way to approach it.

I would recommend doing any spawning within the OnNetworkPostSpawn and not OnNetworkSpawn

This, I can get behind. I'll try and return with the results

This should help with things a bit.
I am going put together a replication project for this and will see if I can replicate what you are describing.

@NoelStephensUnity
Copy link
Collaborator

@MaybeKush
I have verified there is an issue specifically when using a client server network topology and spawning a NetworkObject from within OnNetworkSpawn, OnNetworkPostSpawn, OnInSceneObjectsSpawned, and OnNetworkSessionSynchronized of a NetworkBehaviour attached to the player prefab and using the NetworkManager defined player prefab to handle the spawning of the player prefab.

Until the issue has been resolved, you have two primary options:

Player Prefab Spawning (Client-Server)

  • Player Prefab Spawns Child: Continue to use the NetworkManager to spawn the player and have a NetworkBehaviour component on the player prefab spawn the child.
  • Manual Player Prefab Spawning: Use a MonoBehaviour that is attached to the NetworkManager GameObject (to keep it persistent during the network session).

Below is a project providing you with both examples of how to do this:
PlayerSpawnChild.zip

When you open the project, you should first open the BootStrapScene and look at the ExtendedNetworkManager:

Image

The PlayerSpawnHandler provides you with three possible ways to handle spawning a player prefab and then spawning another network prefab to be parented under the player prefab:
Image

  • NetworkManager Player Prefab
  • Client Connected Callback
  • Client Connected Event

NetworkManager Player Prefab

This option would follow the same flow you have been using with the exception that a client's child object is spawned upon the client finishing being synchronized. The script of interest here is the PlayerSpawnChildAndParent component:
Image

Client Connected Callback and Client Connected Event

Both of these options override the NetworkManager player prefab spawning and will handle spawning the player prefab when either the NetworkManager.OnClientConnectedCallback or NetworkManager.ConnectionEvent actions have been invoked (depending upon which one you pick). The host always spawns its player and child upon starting since it doesn't need to synchronize itself.

Why Is This Required (for the player spawning)

Currently (for connecting clients), this is the logical flow for NetworkManager defined player prefab spawning:

  • When the client is approved for a connection, their player prefab is spawned locally on the server
    • i.e. no CreateObjectMessage is sent (at this point)
      • If you instantiate and spawn a prefab (i.e. the child) at this time a CreateObjectMessage will be sent to all clients.
      • If you parent the spawned (child) object, then a ParentSyncMessage will be sent.
      • Both of the above messages will be sent prior to the synchronization message.
  • Next, the server then builds the synchronization scene event and sends that message to the client so the client can synchronize everything that is spawned.
    • This includes the locally spawned player prefab.
    • This will also include any additional network prefabs you spawned during the player prefab spawn process.
      • This means the connecting client will spawn the child network prefab prior to synchronizing.
      • This also means that the client's player is not spawned yet, so any parenting message received will be deferred until the client is synchronized.
  • While the client is being synchronized (which includes handling synchronizing parenting for the first time), it will see the child object is already spawned and ignore that portion of the synchronization.
    • This means the child will not properly be parented.

Either case, I am marking this issue as a bug because I believe we can change the order of operations to:

  • Server/Host builds the synchronization data and sends the synchronization message to the client.
  • Server spawns the player prefab like it would a dynamically spawned prefab (with the exception that it is the player).
    • This would generate the CreateObjectMessage that would proceed the synchronization message.
      • If the player prefab spawned any network prefabs during this time and/or parented them those messages would proceed the player prefab's CreateObjectMessage.

However, until we get this fix in place you will need to use one of the other techniques I provided in the above attached example project.

Thank you for your patience on this issue.

@NoelStephensUnity NoelStephensUnity added type:bug Bug Report priority:medium This issue has medium priority and may take some time to be resolved stat:import Status - Issue is going to be saved internally and removed type:support Questions or other support stat:awaiting-response Awaiting response from author. This label should be added manually. labels Mar 17, 2025
@NoelStephensUnity NoelStephensUnity self-assigned this Mar 18, 2025
@michalChrobot michalChrobot added stat:imported Status - Issue is tracked internally at Unity and removed stat:import Status - Issue is going to be saved internally labels Mar 18, 2025
@michalChrobot michalChrobot added the stat:awaiting-response Awaiting response from author. This label should be added manually. label Apr 1, 2025
@michalChrobot michalChrobot removed the stat:awaiting-response Awaiting response from author. This label should be added manually. label Apr 10, 2025
@NoelStephensUnity
Copy link
Collaborator

@MaybeKush @kevincastejon
If you have using NGO v2.x then you might update to v2.3.1 and see if that fixes the issue with instantiating, spawning, and parenting within the OnNetworkSpawn or OnNetworkPostSpawn. There was a bug found within the ParentSyncMessage that did not properly defer the parenting message if the parent was not yet spawned (which is what would happen if you instantiate, spawn, and parent within another NetworkObjet's OnNetworkSpawn or OnNetworkPostSpawn methods).

This same fix will be in v1.13.0 via the #3388 backport (this should be soon but I can't give an exact date of when this package will be available).

@github-actions github-actions bot added the stat:awaiting-response Awaiting response from author. This label should be added manually. label Apr 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority:medium This issue has medium priority and may take some time to be resolved stat:awaiting-response Awaiting response from author. This label should be added manually. stat:imported Status - Issue is tracked internally at Unity type:bug Bug Report
Projects
None yet
Development

No branches or pull requests

5 participants