@@ -34,6 +34,12 @@ public abstract class NetworkVariableBase : IDisposable
3434 private protected NetworkBehaviour m_NetworkBehaviour ;
3535 private NetworkManager m_InternalNetworkManager ;
3636
37+ // Determines if this NetworkVariable has been "initialized" to prevent initializing more than once which can happen when first
38+ // instantiated and spawned. If this NetworkVariable instance is on an in-scene placed NetworkObject =or= a pooled NetworkObject
39+ // that can persist between sessions and/or be recycled we need to reset the LastUpdateSent value prior to spawning otherwise
40+ // this NetworkVariableBase property instance will not update until the last session time used.
41+ internal bool HasBeenInitialized { get ; private set ; }
42+
3743 public NetworkBehaviour GetBehaviour ( )
3844 {
3945 return m_NetworkBehaviour ;
@@ -49,37 +55,82 @@ internal void LogWritePermissionError()
4955 Debug . LogError ( GetWritePermissionError ( ) ) ;
5056 }
5157
52- private protected NetworkManager m_NetworkManager
53- {
54- get
55- {
56- if ( m_InternalNetworkManager == null && m_NetworkBehaviour && m_NetworkBehaviour . NetworkObject ? . NetworkManager )
57- {
58- m_InternalNetworkManager = m_NetworkBehaviour . NetworkObject ? . NetworkManager ;
59- }
60- return m_InternalNetworkManager ;
61- }
62- }
58+ private protected NetworkManager m_NetworkManager => m_InternalNetworkManager ;
6359
6460 /// <summary>
6561 /// Initializes the NetworkVariable
6662 /// </summary>
6763 /// <param name="networkBehaviour">The NetworkBehaviour the NetworkVariable belongs to</param>
6864 public void Initialize ( NetworkBehaviour networkBehaviour )
6965 {
70- m_InternalNetworkManager = null ;
66+ // If we have already been initialized, then exit early.
67+ // This can happen on the very first instantiation and spawning of the associated NetworkObject
68+ if ( HasBeenInitialized )
69+ {
70+ return ;
71+ }
72+
73+ // Throw an exception if there is an invalid NetworkBehaviour parameter
74+ if ( ! networkBehaviour )
75+ {
76+ throw new Exception ( $ "[{ GetType ( ) . Name } ][Initialize] { nameof ( NetworkBehaviour ) } parameter passed in is null!") ;
77+ }
7178 m_NetworkBehaviour = networkBehaviour ;
72- if ( m_NetworkBehaviour && m_NetworkBehaviour . NetworkObject ? . NetworkManager )
79+
80+ // Throw an exception if there is no NetworkManager available
81+ if ( ! m_NetworkBehaviour . NetworkManager )
7382 {
74- m_InternalNetworkManager = m_NetworkBehaviour . NetworkObject ? . NetworkManager ;
83+ // Exit early if there has yet to be a NetworkManager assigned.
84+ // This is ok because Initialize is invoked multiple times until
85+ // it is considered "initialized".
86+ return ;
87+ }
7588
76- if ( m_NetworkBehaviour . NetworkManager . NetworkTimeSystem != null )
77- {
78- UpdateLastSentTime ( ) ;
79- }
89+ if ( ! m_NetworkBehaviour . NetworkObject )
90+ {
91+ // Exit early if there has yet to be a NetworkObject assigned.
92+ // This is ok because Initialize is invoked multiple times until
93+ // it is considered "initialized".
94+ return ;
8095 }
8196
97+ if ( ! m_NetworkBehaviour . NetworkObject . NetworkManagerOwner )
98+ {
99+ // Exit early if there has yet to be a NetworkManagerOwner assigned
100+ // to the NetworkObject. This is ok because Initialize is invoked
101+ // multiple times until it is considered "initialized".
102+ return ;
103+ }
104+ m_InternalNetworkManager = m_NetworkBehaviour . NetworkObject . NetworkManagerOwner ;
105+
82106 OnInitialize ( ) ;
107+
108+ // Some unit tests don't operate with a running NetworkManager.
109+ // Only update the last time if there is a NetworkTimeSystem.
110+ if ( m_InternalNetworkManager . NetworkTimeSystem != null )
111+ {
112+ // Update our last sent time relative to when this was initialized
113+ UpdateLastSentTime ( ) ;
114+
115+ // At this point, this instance is considered initialized
116+ HasBeenInitialized = true ;
117+ }
118+ else if ( m_InternalNetworkManager . LogLevel == LogLevel . Developer )
119+ {
120+ Debug . LogWarning ( $ "[{ m_NetworkBehaviour . name } ][{ m_NetworkBehaviour . GetType ( ) . Name } ][{ GetType ( ) . Name } ][Initialize] { nameof ( NetworkManager ) } has no { nameof ( NetworkTimeSystem ) } assigned!") ;
121+ }
122+ }
123+
124+ /// <summary>
125+ /// Deinitialize is invoked when a NetworkObject is despawned.
126+ /// This allows for a recyled NetworkObject (in-scene or pooled)
127+ /// to be properly initialized upon the next use/spawn.
128+ /// </summary>
129+ internal void Deinitialize ( )
130+ {
131+ // When despawned, reset the HasBeenInitialized so if the associated NetworkObject instance
132+ // is recylced (i.e. in-scene placed or pooled) it will re-initialize the LastUpdateSent time.
133+ HasBeenInitialized = false ;
83134 }
84135
85136 /// <summary>
0 commit comments