99
1010namespace DocumentationCodeSamples
1111{
12- public static class FastBufferExtensions
12+ internal static class FastBufferExtensions
1313 {
14- public static void WriteValueSafe ( this FastBufferWriter writer , in Health health )
14+ public static void WriteValueSafe ( this FastBufferWriter writer , in TestSerializationDocs . Health health )
1515 {
1616 writer . WriteValueSafe ( health . MaxHealth ) ;
1717 writer . WriteValueSafe ( health . CurrentHealth ) ;
1818 }
1919
20- public static void ReadValueSafe ( this FastBufferReader reader , out Health health )
20+ public static void ReadValueSafe ( this FastBufferReader reader , out TestSerializationDocs . Health health )
2121 {
2222 reader . ReadValueSafe ( out uint max ) ;
2323 reader . ReadValueSafe ( out int current ) ;
24- health = new Health { MaxHealth = max , CurrentHealth = current } ;
24+ health = new TestSerializationDocs . Health { MaxHealth = max , CurrentHealth = current } ;
2525 }
2626 }
2727
28- #region HealthExample
29- public struct Health
30- {
31- public uint MaxHealth ;
32- public int CurrentHealth ;
33-
34- // Register our custom serialization on load
35- [ InitializeOnLoadMethod ]
36- public static void RegisterHealthSerialization ( )
37- {
38- // You can reuse the FastBufferWriter and FastBufferReader extension methods we wrote above
39- UserNetworkVariableSerialization < Health > . WriteValue = FastBufferExtensions . WriteValueSafe ;
40- UserNetworkVariableSerialization < Health > . ReadValue = FastBufferExtensions . ReadValueSafe ;
41-
42- // Here is where you register your custom delta handling.
43- UserNetworkVariableSerialization < Health > . WriteDelta = WriteDelta ;
44- UserNetworkVariableSerialization < Health > . ReadDelta = ReadDelta ;
4528
46- // You can also use lambda expressions to register functions
47- UserNetworkVariableSerialization < Health > . DuplicateValue = ( in Health value , ref Health duplicatedValue ) => { duplicatedValue = value ; } ;
48- }
29+ internal class TestSerializationDocs : NetcodeIntegrationTest
30+ {
31+ #region HealthExample
4932
50- // We can use an enum to indicate which field has changed for the delta change.
51- // This lets us save bandwidth when only one value has changed.
52- // In the case of Health, we expect CurrentHealth to change much more often than MaxHealth
53- // Implementing WriteDelta saves us bandwidth on not sending the MaxHealth every time CurrentHealth changes.
54- internal enum ChangeType : byte
33+ public struct Health
5534 {
56- MaxHealth ,
57- CurrentHealth ,
58- All ,
59- }
35+ public uint MaxHealth ;
36+ public int CurrentHealth ;
6037
61- public static void WriteDelta ( FastBufferWriter writer , in Health value , in Health previousValue )
62- {
63- if ( value . MaxHealth == previousValue . MaxHealth && value . CurrentHealth != previousValue . CurrentHealth )
38+ // Register our custom serialization on load
39+ [ InitializeOnLoadMethod ]
40+ public static void RegisterHealthSerialization ( )
6441 {
65- // If only our CurrentHealth has changed, we can send the CurrentHealth enum with only the updated CurrentHealth value
66- writer . WriteValueSafe ( ChangeType . CurrentHealth ) ;
67- writer . WriteValueSafe ( value . CurrentHealth ) ;
68- }
69- else if ( value . CurrentHealth == previousValue . CurrentHealth && value . MaxHealth != previousValue . MaxHealth )
70- {
71- // If only our MaxHealth has changed, we can send the MaxHealth enum with only the updated MaxHealth value
72- writer . WriteValueSafe ( ChangeType . MaxHealth ) ;
73- writer . WriteValueSafe ( value . MaxHealth ) ;
42+ // You can reuse the FastBufferWriter and FastBufferReader extension methods we wrote above
43+ UserNetworkVariableSerialization < Health > . WriteValue = FastBufferExtensions . WriteValueSafe ;
44+ UserNetworkVariableSerialization < Health > . ReadValue = FastBufferExtensions . ReadValueSafe ;
45+
46+ // Here is where you register your custom delta handling.
47+ UserNetworkVariableSerialization < Health > . WriteDelta = WriteDelta ;
48+ UserNetworkVariableSerialization < Health > . ReadDelta = ReadDelta ;
49+
50+ // You can also use lambda expressions to register functions
51+ UserNetworkVariableSerialization < Health > . DuplicateValue = ( in Health value , ref Health duplicatedValue ) => { duplicatedValue = value ; } ;
7452 }
75- else
53+
54+ // We can use an enum to indicate which field has changed for the delta change.
55+ // This lets us save bandwidth when only one value has changed.
56+ // In the case of Health, we expect CurrentHealth to change much more often than MaxHealth
57+ // Implementing WriteDelta saves us bandwidth on not sending the MaxHealth every time CurrentHealth changes.
58+ internal enum ChangeType : byte
7659 {
77- // If both values have changed, we need to serialize both values.
78- writer . WriteValueSafe ( ChangeType . All ) ;
79- writer . WriteValueSafe ( value . MaxHealth ) ;
80- writer . WriteValueSafe ( value . CurrentHealth ) ;
60+ MaxHealth ,
61+ CurrentHealth ,
62+ All ,
8163 }
82- }
83-
84- public static void ReadDelta ( FastBufferReader reader , ref Health value )
85- {
86- // First we read what type of change we've received
87- reader . ReadValueSafe ( out ChangeType changeType ) ;
8864
89- // Then we read the data in our delta message, based on what type of change we've received.
90- switch ( changeType )
65+ public static void WriteDelta ( FastBufferWriter writer , in Health value , in Health previousValue )
9166 {
92- case ChangeType . CurrentHealth :
67+ if ( value . MaxHealth == previousValue . MaxHealth && value . CurrentHealth != previousValue . CurrentHealth )
9368 {
94- reader . ReadValueSafe ( out value . CurrentHealth ) ;
95- break ;
69+ // If only our CurrentHealth has changed, we can send the CurrentHealth enum with only the updated CurrentHealth value
70+ writer . WriteValueSafe ( ChangeType . CurrentHealth ) ;
71+ writer . WriteValueSafe ( value . CurrentHealth ) ;
9672 }
97- case ChangeType . MaxHealth :
73+ else if ( value . CurrentHealth == previousValue . CurrentHealth && value . MaxHealth != previousValue . MaxHealth )
9874 {
99- reader . ReadValueSafe ( out value . MaxHealth ) ;
100- break ;
75+ // If only our MaxHealth has changed, we can send the MaxHealth enum with only the updated MaxHealth value
76+ writer . WriteValueSafe ( ChangeType . MaxHealth ) ;
77+ writer . WriteValueSafe ( value . MaxHealth ) ;
10178 }
102- case ChangeType . All :
79+ else
10380 {
104- reader . ReadValueSafe ( out value . MaxHealth ) ;
105- reader . ReadValueSafe ( out value . CurrentHealth ) ;
106- break ;
81+ // If both values have changed, we need to serialize both values.
82+ writer . WriteValueSafe ( ChangeType . All ) ;
83+ writer . WriteValueSafe ( value . MaxHealth ) ;
84+ writer . WriteValueSafe ( value . CurrentHealth ) ;
10785 }
10886 }
10987
110- }
111- }
112- #endregion
88+ public static void ReadDelta ( FastBufferReader reader , ref Health value )
89+ {
90+ // First we read what type of change we've received
91+ reader . ReadValueSafe ( out ChangeType changeType ) ;
11392
114- internal class TestHealthBehaviour : NetworkBehaviour
115- {
116- internal readonly NetworkVariable < Health > HealthVar = new ( ) ;
93+ // Then we read the data in our delta message, based on what type of change we've received.
94+ switch ( changeType )
95+ {
96+ case ChangeType . CurrentHealth :
97+ {
98+ reader . ReadValueSafe ( out value . CurrentHealth ) ;
99+ break ;
100+ }
101+ case ChangeType . MaxHealth :
102+ {
103+ reader . ReadValueSafe ( out value . MaxHealth ) ;
104+ break ;
105+ }
106+ case ChangeType . All :
107+ {
108+ reader . ReadValueSafe ( out value . MaxHealth ) ;
109+ reader . ReadValueSafe ( out value . CurrentHealth ) ;
110+ break ;
111+ }
112+ }
113+ }
114+ }
117115
118- internal Health ReceivedFromRpc ;
116+ #endregion
119117
120- [ Rpc ( SendTo . Everyone ) ]
121- public void SendHealthRpc ( Health health )
118+ internal class TestHealthBehaviour : NetworkBehaviour
122119 {
123- ReceivedFromRpc = health ;
120+ internal readonly NetworkVariable < Health > HealthVar = new ( ) ;
121+
122+ internal Health ReceivedFromRpc ;
123+
124+ [ Rpc ( SendTo . Everyone ) ]
125+ public void SendHealthRpc ( Health health )
126+ {
127+ ReceivedFromRpc = health ;
128+ }
124129 }
125- }
126130
127- internal class TestSerializationDocs : NetcodeIntegrationTest
128- {
129131 protected override int NumberOfClients => 1 ;
130132 private GameObject m_PrefabToSpawn ;
131133
@@ -139,6 +141,7 @@ protected override void OnServerAndClientsCreated()
139141 private ulong m_NetworkObjectIdToTest ;
140142
141143 private bool m_TestingRpc ;
144+
142145 private bool ValidateAllAreEqual ( StringBuilder errorLog )
143146 {
144147 foreach ( var networkManager in m_NetworkManagers )
@@ -148,6 +151,7 @@ private bool ValidateAllAreEqual(StringBuilder errorLog)
148151 errorLog . Append ( $ "[Client-{ networkManager . LocalClientId } ] SpawnedObject not found!") ;
149152 return false ;
150153 }
154+
151155 var healthInstance = localInstance . GetComponent < TestHealthBehaviour > ( ) ;
152156 if ( healthInstance == null )
153157 {
@@ -168,6 +172,7 @@ private bool ValidateAllAreEqual(StringBuilder errorLog)
168172 return false ;
169173 }
170174 }
175+
171176 return true ;
172177 }
173178
@@ -181,7 +186,7 @@ public IEnumerator TestHealthCode()
181186 yield return WaitForSpawnedOnAllOrTimeOut ( authorityInstance . NetworkObjectId ) ;
182187 AssertOnTimeout ( "Failed to spawn network object" ) ;
183188
184- var healthToTest = new Health { MaxHealth = 456 , CurrentHealth = 23 } ;
189+ var healthToTest = new Health { MaxHealth = 456 , CurrentHealth = 23 } ;
185190 m_ExpectedHealth = healthToTest ;
186191 m_TestingRpc = true ;
187192
@@ -191,7 +196,7 @@ public IEnumerator TestHealthCode()
191196 AssertOnTimeout ( "RPC send failed" ) ;
192197
193198 m_TestingRpc = false ;
194- healthToTest = new Health { MaxHealth = 123 , CurrentHealth = 45 } ;
199+ healthToTest = new Health { MaxHealth = 123 , CurrentHealth = 45 } ;
195200 m_ExpectedHealth = healthToTest ;
196201
197202 authorityInstance . HealthVar . Value = healthToTest ;
0 commit comments