Spawn player NetworkObjects in hierarchy efficiently

I’ve been working on a multiplayer VR game for a bit and encountered a pretty big problem: “Spawning NetworkObjects with nested NetworkObjects is only supported for scene objects. Child NetworkObjects will not be spawned over the network!” If I’m interpreting this right, Netcode doesn’t seem to support dynamically spawning prefabs (such as the player prefab) with child NetworkObjects. I found this , but it doesn’t really give any real solution.

Unfortunately, I really gotta do this to assemble the XR Origin, but I need to account for desync stuffs. Do I have to individually disassemble the prefab in files and reassemble at runtime? In that case, will individual parts appear separate briefly due to latency? I’ve been trying to find some kind of way to avoid hardcoding it or making an entire new sort-of network prefab system just to spawn in the players.

The furthest I’ve gone so far is making a script on an otherwise empty player prefab that tries to assemble the actual prefab parts manually, as broken down to individual GameObjects. It’s absolutely gross code tho, and I’m worried about where spawning will place them since they can’t be spawned initially as child objects. Last part that I’m stuck on is that I can’t find a way get the spawned player’s prefab’s clientID for SpawnAsPlayerObject without sending a ServerRpc with ServerRPCParams that will prove the player has ownership.

I believe parenting is on the Netcode roadmap.

But really, what is parenting?

Think about it … :wink:

Parenting simply synchronizes the child’s transform with the parent’s transform. If the parent translates, rotates or scales then so does the child - in relation to the parent’s transform.

Now if you have a script on the supposed child and give it a reference to the parent, and that script runs in LateUpdate a simple code that translates, rotates or scales the child in relation to the other transform it would do the exact same thing. And it isn’t that hard to write, and I believe there’s already a “NetworkTransformSync” kind of behaviour in NGO (or from a user, can’t remember) and once you have that, you can re-use it.

Out of curiosity, once spawned do you plan on unparenting any of the children in this hierarchy of NetworkObjects?

If not, then you can nest NetworkBehaviours at any child generation depth within a hierarchy as long as somewhere up the parent generation hierarchy there is a NetworkObject.

As an example, you can have a network prefab like this:

  • Root (with NetworkObject)

  • Child1-A

  • Child1-B (with NetworkBehaviour)

  • Child1-C

  • Child1-D (with NetworkBehaviour)

  • Child2-A

  • Child2-B

  • Child2-C (with NetworkBehaviour)

  • Etc…

The above would work if you don’t plan on removing the children but you want to speckle your hierarchy with NetworkBehaviours.

Otherwise, if you do plan on removing children then let me know and I can provide some script to handle that.

This would definitely work for most stuff, but I’m fairly sure the TrackedPoseDrivers always center at their relative 0, 0, 0 which (while parented right) is at the XR Origin, correct me tho if I’m wrong.

Sadly, yeah. Planning on making my own grab system to compliment the more analog controls in the game, but my current system involves reparenting the visible hands to give a better grab effect. Something I am wondering though, can you still synchronize transform position/rotation changes of the child GameObjects without them having the NetworkObject component? If not, I dunno if this system will work either

Thanks to yall for your help tho!!

Got an answer to my previous question & kinda found a half-solution on my own, tho its gonna make everything really annoying to do. Watched Valem’s tutorial on this and his solution of having a client & server instance of the player kinda works? It’s gonna be super annoying to deal with, but it might work. Looking forward to when proper prefab support is added!

If the child GameObject (with a NetworkTransform component) was spawned under a NetworkObject (any generation depth) and you move the child GameObject (after spawned) to any location it should continue to synchronize transform deltas.

  • Root Object-1 (with NetworkObject)

  • Child1-A

  • Child1-B (with NetworkBehaviour)

  • Child1-C

  • Child1-D (with NetworkBehaviour & NetworkTransform)

  • Child2-A

  • Child2-B

  • Child2-C (with NetworkBehaviour)

  • Etc…

  • Root Object-2 (with NetworkObject)

  • Child1-A

  • Child2-A

  • Etc.

If you changed Root Object-1 → Child1-D’s parent to be RootObject-2–>Child1-A then Child1-D will still update its NetworkTransform (it will just be routed through messaging as still belonging to Root Object-1).

  • Root Object-1 (with NetworkObject)

  • Child1-A

  • Child1-B (with NetworkBehaviour)

  • Child1-C

  • Child2-A

  • Child2-B

  • Child2-C (with NetworkBehaviour)

  • Etc…

  • Root Object-2 (with NetworkObject)

  • Child1-A

  • Child1-D (with NetworkBehaviour & NetworkTransform)

  • Child2-A

  • Etc.

However, you have to synchronize this type of parenting yourself… you might look at this forum post as I provided some script that does exactly this … once spawned, NetworkBehaviours will function whether they are located under their associated NetworkObject or not… you just need to keep track of any jumbling of parents to handle scenarios where you want the original hierarchy to be “put back together as it was originally spawned”.
You only need to use the NetworkObject.TrySetParent if you are parenting NetworkObject to NetworkObject. If you are parenting a child GameObject with NetworkBehaviour to some other GameObject, you can just set the transform.parent directly.