@@ -1807,7 +1807,15 @@ internal void SpawnInternal(bool destroyWithScene, ulong ownerClientId, bool pla
18071807 }
18081808 }
18091809
1810- NetworkManagerOwner . SpawnManager . AuthorityLocalSpawn ( this , NetworkManagerOwner . SpawnManager . GetNetworkObjectId ( ) , IsSceneObject . HasValue && IsSceneObject . Value , playerObject , ownerClientId , destroyWithScene ) ;
1810+ if ( ! NetworkManagerOwner . SpawnManager . AuthorityLocalSpawn ( this , NetworkManagerOwner . SpawnManager . GetNetworkObjectId ( ) , IsSceneObject . HasValue && IsSceneObject . Value , playerObject , ownerClientId , destroyWithScene ) )
1811+ {
1812+ if ( NetworkManagerOwner . LogLevel <= LogLevel . Normal )
1813+ {
1814+ NetworkLog . LogWarning ( $ "[{ name } ] Failed to finish spawning!") ;
1815+ }
1816+ ResetOnDespawn ( ) ;
1817+ return ;
1818+ }
18111819
18121820 if ( ( NetworkManagerOwner . DistributedAuthorityMode && NetworkManagerOwner . DAHost ) || ( ! NetworkManagerOwner . DistributedAuthorityMode && NetworkManagerOwner . IsServer ) )
18131821 {
@@ -1865,7 +1873,7 @@ public static NetworkObject InstantiateAndSpawn(GameObject networkPrefab, Networ
18651873 /// <summary>
18661874 /// This invokes <see cref="NetworkSpawnManager.InstantiateAndSpawn(NetworkObject, ulong, bool, bool, bool, Vector3, Quaternion)"/>.
18671875 /// </summary>
1868- /// <param name="networkManager">The local instance of the NetworkManager connected to an session in progress.</param>
1876+ /// <param name="networkManager">The local instance of the NetworkManager connected to a session in progress.</param>
18691877 /// <param name="ownerClientId">The owner of the <see cref="NetworkObject"/> instance (defaults to server).</param>
18701878 /// <param name="destroyWithScene">Whether the <see cref="NetworkObject"/> instance will be destroyed when the scene it is located within is unloaded (default is false).</param>
18711879 /// <param name="isPlayerObject">Whether the <see cref="NetworkObject"/> instance is a player object or not (default is false).</param>
@@ -2161,6 +2169,11 @@ internal void SetNetworkParenting(ulong? latestParent, bool worldPositionStays)
21612169 m_CachedWorldPositionStays = worldPositionStays ;
21622170 }
21632171
2172+ internal void ClearNetworkParenting ( )
2173+ {
2174+ m_LatestParent = null ;
2175+ }
2176+
21642177 /// <summary>
21652178 /// Set the parent of the NetworkObject transform.
21662179 /// </summary>
@@ -3304,90 +3317,35 @@ internal static NetworkObject Deserialize(in SerializedObject serializedObject,
33043317 {
33053318 var endOfSynchronizationData = reader . Position + serializedObject . SynchronizationDataSize ;
33063319
3307- byte [ ] instantiationData = null ;
3308- if ( serializedObject . HasInstantiationData )
3309- {
3310- reader . ReadValueSafe ( out instantiationData ) ;
3311- }
3312-
3313-
3314- // Attempt to create a local NetworkObject
3315- var networkObject = networkManager . SpawnManager . CreateLocalNetworkObject ( serializedObject , instantiationData ) ;
3316-
3317-
3318- if ( networkObject == null )
3319- {
3320- // Log the error that the NetworkObject failed to construct
3321- if ( networkManager . LogLevel <= LogLevel . Normal )
3322- {
3323- NetworkLog . LogError ( $ "Failed to spawn { nameof ( NetworkObject ) } for Hash { serializedObject . Hash } .") ;
3324- }
3325-
3326- try
3327- {
3328- // If we failed to load this NetworkObject, then skip past the Network Variable and (if any) synchronization data
3329- reader . Seek ( endOfSynchronizationData ) ;
3330- }
3331- catch ( Exception ex )
3332- {
3333- Debug . LogException ( ex ) ;
3334- }
3320+ // Do the SpawnManager parts of the object spawn
3321+ var succeeded = networkManager . SpawnManager . NonAuthorityLocalSpawn ( in serializedObject , out var networkObject , reader , serializedObject . DestroyWithScene ) ;
33353322
3336- // We have nothing left to do here.
3337- return null ;
3338- }
3339-
3340- networkObject . NetworkManagerOwner = networkManager ;
3341-
3342- // This will get set again when the NetworkObject is spawned locally, but we set it here ahead of spawning
3343- // in order to be able to determine which NetworkVariables the client will be allowed to read.
3344- networkObject . OwnerClientId = serializedObject . OwnerClientId ;
3323+ // Process any deferred messages once the object is 100% finished spawning
3324+ // Ensure this is done whether the spawn succeeds or fails
3325+ networkManager . DeferredMessageManager . ProcessTriggers ( IDeferredNetworkMessageManager . TriggerType . OnSpawn , networkObject . NetworkObjectId ) ;
33453326
3346- // Special Case: Invoke NetworkBehaviour.OnPreSpawn methods here before SynchronizeNetworkBehaviours
3347- networkObject . InvokeBehaviourNetworkPreSpawn ( ) ;
3348-
3349- // Process the remaining synchronization data from the buffer
3350- try
3327+ // If the SpawnManager spawn doesn't succeed, be sure to clean up
3328+ if ( ! succeeded )
33513329 {
3352- // Synchronize NetworkBehaviours
3353- var bufferSerializer = new BufferSerializer < BufferSerializerReader > ( new BufferSerializerReader ( reader ) ) ;
3354- networkObject . SynchronizeNetworkBehaviours ( ref bufferSerializer , networkManager . LocalClientId ) ;
3355-
33563330 // Ensure that the buffer is completely reset
33573331 if ( reader . Position != endOfSynchronizationData )
33583332 {
3359- Debug . LogWarning ( $ "[Size mismatch] Expected: { endOfSynchronizationData } Currently At: { reader . Position } !") ;
3333+ if ( networkManager . LogLevel <= LogLevel . Normal )
3334+ {
3335+ NetworkLog . LogWarning ( $ "[{ networkObject . name } ][Deserialize][Size mismatch] Expected: { endOfSynchronizationData } Currently At: { reader . Position } !") ;
3336+ }
33603337 reader . Seek ( endOfSynchronizationData ) ;
33613338 }
3362- }
3363- catch
3364- {
3365- reader . Seek ( endOfSynchronizationData ) ;
3366- }
33673339
3368- // If we are an in-scene placed NetworkObject and we originally had a parent but when synchronized we are
3369- // being told we do not have a parent, then we want to clear the latest parent so it is not automatically
3370- // "re-parented" to the original parent. This can happen if not unloading the scene and the parenting of
3371- // the in-scene placed Networkobject changes several times over different sessions.
3372- if ( serializedObject . IsSceneObject && ! serializedObject . HasParent && networkObject . m_LatestParent . HasValue )
3373- {
3374- networkObject . m_LatestParent = null ;
3375- }
3376-
3377- // Spawn the NetworkObject
3378- if ( networkObject . IsSpawned )
3379- {
3380- if ( NetworkManager . Singleton . LogLevel <= LogLevel . Error )
3340+ // If the networkObject was created but the spawn failed, the created object needs to be destroyed
3341+ if ( networkObject != null )
33813342 {
3382- NetworkLog . LogErrorServer ( $ "[ { networkObject . name } ] Object- { networkObject . NetworkObjectId } is already spawned!" ) ;
3343+ Destroy ( networkObject . gameObject ) ;
33833344 }
3345+
33843346 return null ;
33853347 }
33863348
3387- // Invoke the non-authority local spawn method
3388- // (It also invokes post spawn and handles processing derferred messages)
3389- networkManager . SpawnManager . NonAuthorityLocalSpawn ( networkObject , serializedObject , serializedObject . DestroyWithScene ) ;
3390-
33913349 if ( serializedObject . SyncObservers )
33923350 {
33933351 foreach ( var observer in serializedObject . Observers )
0 commit comments