-
Notifications
You must be signed in to change notification settings - Fork 447
feat: add pre and post spawn methods #2906
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
feat: add pre and post spawn methods #2906
Conversation
Added NetworkBehaviour.OnNetworkSessionSynchronized and NetworkBehaviour.OnInSceneObjectsSpawned methods. Added test to validate the above methods. Added assets for the test to validate the above methods.
Adding documentation for PR-2906: Unity-Technologies/com.unity.netcode.gameobjects#2906
Thanks!! The limitations of OnNetworkPreSpawn concern me about its utility a bit, but I haven't thought it all the way through. I was kind of expecting it to be more akin to Awake/Start where OnNetworkPreSpawn is fired for ALL NetworkObjects' NetworkBehaviours immediately before OnNetworkSpawn is fired for ALL NetworkObjects' NetworkBehaviours. (When I say "all" I mean every scene net object... obviously dynamically spawned network objects have no relationship to each other in that way.) Is there a use case I'm missing where it is useful to have OnNetworkPreSpawn not wait for IsOwner etc to be set? Is there a use case where it is harmful for OnNetworkPreSpawn to wait like that? There's a fair amount of complexity and nuance (and maybe even overlap?) between OnNetworkSessionSynchronized, OnInSceneObjectsSpawned, and OnNetworkPostSpawn... let me try to make sure we both understand some common things that I want to do in code during the network spawn stage of a scene that cannot use OnNetworkSpawn alone (because other objects may not be spawned yet).
It's ambiguous to me right now if OnInSceneObjectsSpawned will run multiple times on the same scene load...
Will it only run exactly one time on the server and each client for the loading of a given scene? Or is this bulleted list saying that it will fire multiple times? It looks like OnNetworkSessionSynchronized clearly only runs once per client when all NetworkObjects are ready (the host being a client too). This seems like it would solve a lot of my problems!! I think I'm not quite straight in my head yet on what I would use OnInSceneObjectsSpawned for instead. As for OnNetworkPostSpawn, I see this in the documentation:
So that would mean that OnNetworkPostSpawn will fire on one NetworkObject in a loaded scene before potentially any Pre/Spawn/Post stuff has fired at all on some OTHER NetworkObject in that loaded scene? I go back to my Awake/Start analogy, and I think this is a bit of a gotchya for programmers. I guess I was thinking OnNetworkPostSpawn would be what OnNetworkSessionSynchronized is? I appreciate you! |
When deserializing from the inbound message stream buffer, everything is processed in a synchronous fashion. This means that each NetworkObject is:
This happens as the buffer is being parsed, so it would be a complete re-working of that entire process to first instantiate and/or link to NetworkObjects, invoked the prespawn, then spawn the NetworkObjects, then invoke the postspawn (as you describe above).
Here is the order of operations of spawning:
As you pointed out in your scenarios, there are other circumstances where you will want to be assured that everything is spawned and/or at a minimum In-Scene placed NetworkObjects have been spawned (needs a bit of context which is below). In reality there are two conditions where you need to know "when something is spawned" in a client-server topology:
You would place your script that handles accessing B2 within B1's OnNetworkPostSpawn (B2 will have already run through OnNetworkSpawn at that point).
You would place your script action to access the NetworkObject-Y's NetworkBehaviour within one of the NetworkObject-X's NetworkBehaviour's OnInSceneObjectsSpawned overridden method. All in-scene placed NetworkObjects are spawned at that time.
All of the above you would handle within an overridden OnInSceneObjectsSpawned method (assuming all of the above are in-scene placed). Otherwise:
The caveat is if you load scene A and then upon loading scene A you then load Scene B... when handling "cross scene" in-scene placed NetworkObjects you want to wait for the SceneEventType.LoadEventCompleted event for Scene B on say an in-scene placed NetworkObject's NetworkBehaviour contained in scene A. Does this help further clarify the usage? |
Thanks for the long response! Hmmm... would it be simpler for everyone involved if there was just Pre/Spawn/Post where:
The way PostSpawn is described to work now, and the nitty gritty of OnInSceneObjectsSpawned vs OnNetworkSessionSynchronized, is quite a lot to describe and keep in one's brain. PostSpawn seems like a trap and unsafe compared to OnNetworkSessionSynchronized given the descriptions/docs. |
So, I looked into this and the issues I ran into were the distinct different scenarios:
It is the "knowing when everything that should be spawned has been spawned" issue based on the 3 above scenarios. This would require me to do a bit more "heavy lifting" of NetworkManager and the over-all flow from not started to started to shutting down. That I might be able to pull off in v2.0.0, but for v1.x it wouldn't really be possible... well... it would be possible but it wouldn't be done "correctly"... as in I would want to migrate a large portion of stand alone events over to "states" and then have a single event (i.e. NetworkManager.StateUpdated) that would include a state with additional information that most likely would implement some form of interface to access some basic info with additional state specific information that could be acquired via a generic method...which that all would be considered a "breaking change" and is outside of the possibilities for v1.9 For v2 I have more flexibility and could decide to do that (as long as I have enough time relative to all other things needed to be done). |
Thanks for the insights! |
This PR focuses on providing users with additional
NetworkBehaviour
virtual methods that remove the need to subscribe to scene events or client connected callbacks while also removing the need to know or track order of operations when it comes to crossNetworkObject
access in problematic areas (scene loading and synchronization).Adding pre and post spawn methods to
NetworkBehaviour
components. This can be useful for:Adding
NetworkBehaviour.OnNetworkSessionSynchronized
andNetworkBehaviour.OnInSceneObjectsSpawned
convenience methods that provide users with the ability to handle post-synchronization and/or post-scene loading actions.NetworkBehaviour.OnNetworkSessionSynchronized
: A client-side only convenience method that is invoked on every NetworkBehaviour once a newly connected client has finished synchronizing and allNetworkObject
s are spawned.NetworkBehaviour.OnInSceneObjectsSpawned
: A convenience method (requires scene management to be enabled) that is invoked when:NetworkObject
s in the currently loaded scene(s) have been spawned.NetworkObject
s have been spawned.Clearing the m_ChildNetworkBehaviours on Awake to resolve an issue with not completely resetting a
NetworkObject
component's childNetworkBehaviour
components.Implements portions of epic: MTT-8470
MTT-8368
MTT-8400
Also:
fix: #2892
fix: #2870
Changelog
Added:
NetworkBehaviour.OnNetworkPreSpawn
andNetworkBehaviour.OnNetworkPostSpawn
methods that provide the ability to handle pre and post spawning actions during theNetworkObject
spawn sequence.Added: A client-side only
NetworkBehaviour.OnNetworkSessionSynchronized
convenience method that is invoked on allNetworkBehaviour
s after a newly joined client has finished synchronizing with the network session in progress.Added:
NetworkBehaviour.OnInSceneObjectsSpawned
convenience method that is invoked when all in-sceneNetworkObject
s have been spawned after a scene has been loaded or upon a host or server starting.Fixed: Issue where a
NetworkObject
component's associatedNetworkBehaviour
components would not be detected if scene loading is disabled in the editor and the currently loaded scene has in-scene placedNetworkObject
s.Testing and Documentation
NetworkBehaviourPrePostSpawnTests.OnNetworkPreAndPostSpawn
(validates dynamically spawned)NetworkBehaviourSessionSynchronized.InScenePlacedSessionSynchronized
(validates in-scene placed)