Manually set `NetworkObjectId`
See original GitHub issueIs your feature request related to a problem? Please describe.
I am porting a single user app to a multi user experience and need to make sure interactable objects are synced. My existing app loads 3D meshes from disk at runtime and dynamically instantiates GameObjects for the mesh. I would like to keep the current loading/spawning logic and just add a NetworkObject
component and tell NGO to use the same NetworkObjectId
for the matching GameObjects (e.g. using the GameObject name/scene path as a unique identifier).
Describe the solution you’d like
I would like to add a NetworkObject
component manually on each client and tell NGO to treat it like a NetworkObject
that was spawned by the server, ideally by manually assigning a NetworkObjectId
and registering the object with NGO.
Describe alternatives you’ve considered
Register the GameObjects using e.g. AddNetworkPrefab
and calling Spawn
on the server, or wrapping the dynamic GameObject with a pre-defined prefab.
Additional context Having to rely on NGO to instantiate networked GameObjects feels like an unneccessary step if there is existing spawning/instantiation logic in place. I understand that this is more of an advanced use case and ideally one would design their app/game with the NGO spawning approach in mind but this is not always the case. So far I have not found a good workaround.
Issue Analytics
- State:
- Created 7 months ago
- Comments:5 (3 by maintainers)
Top GitHub Comments
@FreshlyBrewedCode Your details helped clear up a bunch of fuzzy spots for me. Thank you for that! 👍
So, this does indeed sound like an advanced feature request and would be something that could potentially take longer than you might want for your project. The method, using “blank network prefabs”, I described would be the best way you can handle this without running into any major issues.
The biggest road block you would find out about if you tried to make your own PR is all of the pre-runtime code generation that has to occur. I would take some time to browse through everything that is handled during ILPP before attempting to make a PR or create a fork of your own. This is actually the primary reason behind the lack of runtime dynamic NetworkObject/network prefab generation support in NGO today.
My recommendation for your project would be to approach it using pre-created “blank Network Prefabs” that have the framework of what you would need to make specific 3D Mesh sets operate properly and then dynamically add the MeshRenderer and MeshFilter to existing or newly created GameObjects.
Side Note: Since you can have one (1) NetworkObject that has many nested NetworkTransforms, you would only need to create the “frame” for each type of 3D mesh that you need (i.e. if your 3D Meshes have complex hierarchies). Blank Network Prefab A
However, there is something that we don’t recommend as it can get complex quickly but… 😸 you seem like you are adventurous…and it is really the only other thing I could think of that “may” be something you might look into…with caution!
Contemplate this: Once a NetworkObject (that could have many children with several NetworkBehaviours nested under it in children) is spawned… there is nothing saying that you can’t --migrate-- the children to some completely different GameObject.
(Again we don’t officially support this approach but it just so happens that it can be done…with a bunch of additional tracking code that can become complex quickly!)
You might spawn a “blank Network Prefab” that has many different NetworkBehaviours associated with it but only one NetworkObject at the root of the prefab.
So, once it is spawned… everything is “initialized” for NGO messaging and the like. If you were to migrate a child to a completely different GameObject then it would still send/receive messages and work as expected.
========================================
GameObject (NetworkObject)
GameObject Child of Root (NetworkTransform) – Removed and now has no parent
========================================
Again, this is not an officially supported (or recommended) approach as you still need to handle late joining clients. So, you would need a way to track what child from which instance was being used for a specific runtime loaded 3D Mesh. This information would need to be applied when the instances were spawned… which theoretically (again…not saying we recommend or support this approach) you could use the
override void OnSynchronize<T>
functionality to send this information needed to pull apart the spawned “blank Network Prefab” and use the “pieces/parts” of it for various things that you are loading during runtime. This would need to be synchronized to happen after the original “blank Network Prefab” was spawned. so there are some timing related things you would need to map out for this approach. Since we don’t support this approach you could run into a scenario where a future update makes any works towards this obsolete/unusable (as another caution).The recommend (and safest approach) is to create a set of “blank Network Prefabs” that you dynamically add the MeshFilter and MeshRenderer to once the 3D Mesh is loaded or that you parent the 3D mesh under a GameObject of the newly spawned “blank Network Prefab” instance. While this might seem time consuming it is worth contemplating the time that would take over the other possible alternatives and then make a decision from there.
I will go ahead and mark this issue for import, but I also wanted to make sure you understood the technical issues behind this particular limitation in NGO are “semi-hidden” as there is ILPP related things that have to execute ahead of time before entering into play mode/runtime so just exposing methods to assign a NetworkObjectId or NetwokrBehaviourId makes the source code look like it is “logically possible”…but that is slightly deceiving as there still is the code generation side of things that happens when you enter into play mode or make a stand alone build.
@FreshlyBrewedCode Your solution is clever indeed! 💯