ViewSynchronization
How do I use View Synchronization
Below are practical examples compiled from projects for learning and reference purposes
Featured Snippets
File name: PhotonConverter.cs
Copy
189 static void ConvertToPhotonAPI(string file)
190 {
191 string text = File.ReadAllText(file);
192
193 bool isJS = file.Contains(".js");
194
195 file = file.Replace("\\", "/"); // Get Class name for JS
196 string className = file.Substring(file.LastIndexOf("/")+1);
197 className = className.Substring(0, className.IndexOf("."));
198
199
200 //REGEXP STUFF
201 //Valid are: Space { } , /n /r
202 //string NOT_VAR = @"([^A-Za-z0-9_\[\]\.]+)";
203 string NOT_VAR_WITH_DOT = @"([^A-Za-z0-9_]+)";
204
205 //string VAR_NONARRAY = @"[^A-Za-z0-9_]";
206
207
208 //NetworkView
209 {
210 text = PregReplace(text, NOT_VAR_WITH_DOT + "NetworkView" + NOT_VAR_WITH_DOT, "$1PhotonView$2");
211 text = PregReplace(text, NOT_VAR_WITH_DOT + "networkView" + NOT_VAR_WITH_DOT, "$1photonView$2");
212 text = PregReplace(text, NOT_VAR_WITH_DOT + "stateSynchronization" + NOT_VAR_WITH_DOT, "$1synchronization$2");
213 text = PregReplace(text, NOT_VAR_WITH_DOT + "NetworkStateSynchronization" + NOT_VAR_WITH_DOT, "$1ViewSynchronization$2"); // map Unity enum to ours
214 //.RPC
215 text = PregReplace(text, NOT_VAR_WITH_DOT + "RPCMode.Server" + NOT_VAR_WITH_DOT, "$1PhotonTargets.MasterClient$2");
216 text = PregReplace(text, NOT_VAR_WITH_DOT + "RPCMode" + NOT_VAR_WITH_DOT, "$1PhotonTargets$2");
217 }
218
219 //NetworkMessageInfo: 100%
220 {
221 text = PregReplace(text, NOT_VAR_WITH_DOT + "NetworkMessageInfo" + NOT_VAR_WITH_DOT, "$1PhotonMessageInfo$2");
222 text = PregReplace(text, NOT_VAR_WITH_DOT + "networkView" + NOT_VAR_WITH_DOT, "$1photonView$2");
223 }
224
225 //NetworkViewID:
226 {
227 text = PregReplace(text, NOT_VAR_WITH_DOT + "NetworkViewID" + NOT_VAR_WITH_DOT, "$1int$2"); //We simply use an int
228 }
229
230 //NetworkPlayer
231 {
232 text = PregReplace(text, NOT_VAR_WITH_DOT + "NetworkPlayer" + NOT_VAR_WITH_DOT, "$1PhotonPlayer$2");
233 }
234
235 //Network
236 {
237 //Monobehaviour callbacks
238 {
239 text = PregReplace(text, NOT_VAR_WITH_DOT + "OnPlayerConnected" + NOT_VAR_WITH_DOT, "$1OnPhotonPlayerConnected$2");
240 text = PregReplace(text, NOT_VAR_WITH_DOT + "OnPlayerDisconnected" + NOT_VAR_WITH_DOT, "$1OnPhotonPlayerDisconnected$2");
241 text = PregReplace(text, NOT_VAR_WITH_DOT + "OnNetworkInstantiate" + NOT_VAR_WITH_DOT, "$1OnPhotonInstantiate$2");
242 text = PregReplace(text, NOT_VAR_WITH_DOT + "OnSerializeNetworkView" + NOT_VAR_WITH_DOT, "$1OnPhotonSerializeView$2");
243 text = PregReplace(text, NOT_VAR_WITH_DOT + "BitStream" + NOT_VAR_WITH_DOT, "$1PhotonStream$2");
244
245 //Not completely the same meaning
246 text = PregReplace(text, NOT_VAR_WITH_DOT + "OnServerInitialized" + NOT_VAR_WITH_DOT, "$1OnCreatedRoom$2");
247 text = PregReplace(text, NOT_VAR_WITH_DOT + "OnConnectedToServer" + NOT_VAR_WITH_DOT, "$1OnJoinedRoom$2");
248
249 text = PregReplace(text, NOT_VAR_WITH_DOT + "OnFailedToConnectToMasterServer" + NOT_VAR_WITH_DOT, "$1OnFailedToConnectToPhoton$2");
250 text = PregReplace(text, NOT_VAR_WITH_DOT + "OnFailedToConnect" + NOT_VAR_WITH_DOT, "$1OnFailedToConnect_OBSELETE$2");
251 }
252
253 //Variables
254 {
255
256 text = PregReplace(text, NOT_VAR_WITH_DOT + "Network.connections" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.playerList$2");
257 text = PregReplace(text, NOT_VAR_WITH_DOT + "Network.isServer" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.isMasterClient$2");
258 text = PregReplace(text, NOT_VAR_WITH_DOT + "Network.isClient" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.isNonMasterClientInRoom$2");
259
260 text = PregReplace(text, NOT_VAR_WITH_DOT + "NetworkPeerType" + NOT_VAR_WITH_DOT, "$1ConnectionState$2");
261 text = PregReplace(text, NOT_VAR_WITH_DOT + "Network.peerType" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.connectionState$2");
262 text = PregReplace(text, NOT_VAR_WITH_DOT + "ConnectionState.Server" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.isMasterClient$2");
263 text = PregReplace(text, NOT_VAR_WITH_DOT + "ConnectionState.Client" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.isNonMasterClientInRoom$2");
264 text = PregReplace(text, NOT_VAR_WITH_DOT + "PhotonNetwork.playerList.Length" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.playerList.Count$2");
265
266 /*DROPPED:
267 minimumAllocatableViewIDs
268 natFacilitatorIP is dropped
269 natFacilitatorPort is dropped
270 connectionTesterIP
271 connectionTesterPort
272 proxyIP
273 proxyPort
274 useProxy
275 proxyPassword
276 */
277 }
278
279 //Methods
280 {
281 text = PregReplace(text, NOT_VAR_WITH_DOT + "Network.InitializeServer" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.CreateRoom$2");
282 text = PregReplace(text, NOT_VAR_WITH_DOT + "Network.Connect" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.JoinRoom$2");
283 text = PregReplace(text, NOT_VAR_WITH_DOT + "Network.GetAveragePing" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.GetPing$2");
284 text = PregReplace(text, NOT_VAR_WITH_DOT + "Network.GetLastPing" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.GetPing$2");
285 /*DROPPED:
286 TestConnection
287 TestConnectionNAT
288 HavePublicAddress
289 */
290 }
291
292 //Overall
293 text = PregReplace(text, NOT_VAR_WITH_DOT + "Network" + NOT_VAR_WITH_DOT, "$1PhotonNetwork$2");
294
295
296 //Changed methods
297 string ignoreMe = @"([A-Za-z0-9_\[\]\(\) ]+)";
298
299 text = PregReplace(text, NOT_VAR_WITH_DOT + "PhotonNetwork.GetPing\\(" + ignoreMe+"\\);", "$1PhotonNetwork.GetPing();");
300 text = PregReplace(text, NOT_VAR_WITH_DOT + "PhotonNetwork.CloseConnection\\(" + ignoreMe+","+ignoreMe+"\\);", "$1PhotonNetwork.CloseConnection($2);");
301
302 }
303
304 //General
305 {
306 if (text.Contains("Photon")) //Only use the PhotonMonoBehaviour if we use photonView and friends.
307 {
308 if (isJS)//JS
309 {
310 if (text.Contains("extends MonoBehaviour"))
311 text = PregReplace(text, "extends MonoBehaviour", "extends Photon.MonoBehaviour");
312 else
313 text = "class " + className + " extends Photon.MonoBehaviour {\n" + text + "\n}";
314 }
315 else //C#
316 text = PregReplace(text, ": MonoBehaviour", ": Photon.MonoBehaviour");
317 }
318 }
319
320 File.WriteAllText(file, text);
321 }
File name: PhotonConverter.cs
Copy
351 static int ConvertNetworkView(NetworkView[] netViews, bool isScene)
352 {
353 for (int i = netViews.Length - 1; i >= 0; i--)
354 {
355 NetworkView netView = netViews[i];
356 PhotonView view = netView.gameObject.AddComponent
357 if (isScene)
358 {
359 //Get scene ID
360 string str = netView.viewID.ToString().Replace("SceneID: ", "");
361 int firstSpace = str.IndexOf(" ");
362 str = str.Substring(0, firstSpace);
363 int oldViewID = int.Parse(str);
364
365 view.viewID = oldViewID;
366 EditorUtility.SetDirty(view);
367 EditorUtility.SetDirty(view.gameObject);
368 }
369 view.observed = netView.observed;
370 if (netView.stateSynchronization == NetworkStateSynchronization.Unreliable)
371 {
372 view.synchronization = ViewSynchronization.Unreliable;
373 }
374 else if (netView.stateSynchronization == NetworkStateSynchronization.ReliableDeltaCompressed)
375 {
376 view.synchronization = ViewSynchronization.ReliableDeltaCompressed;
377 }
378 else
379 {
380 view.synchronization = ViewSynchronization.Off;
381 }
382 DestroyImmediate(netView, true);
383 }
384 AssetDatabase.Refresh();
385 AssetDatabase.SaveAssets();
386
387 return netViews.Length;
388 }
File name: PhotonViewInspector.cs
Copy
21 public override void OnInspectorGUI()
22 {
23 #if UNITY_3_5
24 EditorGUIUtility.LookLikeInspector();
25 #endif
26 //EditorGUI.indentLevel = 1;
27
28 m_Target = (PhotonView)this.target;
29 bool isProjectPrefab = EditorUtility.IsPersistent(m_Target.gameObject);
30
31 if( m_Target.ObservedComponents == null )
32 {
33 m_Target.ObservedComponents = new System.Collections.Generic.List
34 }
35
36 if( m_Target.ObservedComponents.Count == 0 )
37 {
38 m_Target.ObservedComponents.Add( null );
39 }
40
41 EditorGUILayout.BeginHorizontal();
42 // Owner
43 if (isProjectPrefab)
44 {
45 EditorGUILayout.LabelField("Owner:", "Set at runtime");
46 }
47 else if (m_Target.isSceneView)
48 {
49 EditorGUILayout.LabelField("Owner", "Scene");
50 }
51 else
52 {
53 PhotonPlayer owner = m_Target.owner;
54 string ownerInfo = (owner != null) ? owner.name : "
55
56 if (string.IsNullOrEmpty(ownerInfo))
57 {
58 ownerInfo = "
59 }
60
61 EditorGUILayout.LabelField("Owner", "[" + m_Target.ownerId + "] " + ownerInfo);
62 }
63
64 // ownership requests
65 EditorGUI.BeginDisabledGroup(Application.isPlaying);
66 m_Target.ownershipTransfer = (OwnershipOption)EditorGUILayout.EnumPopup(m_Target.ownershipTransfer, GUILayout.Width(100));
67 EditorGUI.EndDisabledGroup();
68
69 EditorGUILayout.EndHorizontal();
70
71
72 // View ID
73 if (isProjectPrefab)
74 {
75 EditorGUILayout.LabelField("View ID", "Set at runtime");
76 }
77 else if (EditorApplication.isPlaying)
78 {
79 EditorGUILayout.LabelField("View ID", m_Target.viewID.ToString());
80 }
81 else
82 {
83 int idValue = EditorGUILayout.IntField("View ID [1.."+(PhotonNetwork.MAX_VIEW_IDS-1)+"]", m_Target.viewID);
84 m_Target.viewID = idValue;
85 }
86
87
88
89 // Locally Controlled
90 if (EditorApplication.isPlaying)
91 {
92 string masterClientHint = PhotonNetwork.isMasterClient ? "(master)" : "";
93 EditorGUILayout.Toggle("Controlled locally: " + masterClientHint, m_Target.isMine);
94 }
95
96
97
98 //DrawOldObservedItem();
99 ConvertOldObservedItemToObservedList();
100
101
102 // ViewSynchronization (reliability)
103 if (m_Target.synchronization == ViewSynchronization.Off)
104 {
105 GUI.color = Color.grey;
106 }
107
108 EditorGUILayout.PropertyField( serializedObject.FindProperty( "synchronization" ), new GUIContent( "Observe option:" ) );
109
110 if( m_Target.synchronization != ViewSynchronization.Off &&
111 m_Target.ObservedComponents.FindAll( item => item != null ).Count == 0 )
112 {
113 GUILayout.BeginVertical( GUI.skin.box );
114 GUILayout.Label( "Warning", EditorStyles.boldLabel );
115 GUILayout.Label( "Setting the synchronization option only makes sense if you observe something." );
116 GUILayout.EndVertical();
117 }
118
119 /*ViewSynchronization vsValue = (ViewSynchronization)EditorGUILayout.EnumPopup("Observe option:", m_Target.synchronization);
120 if (vsValue != m_Target.synchronization)
121 {
122 m_Target.synchronization = vsValue;
123 if (m_Target.synchronization != ViewSynchronization.Off && m_Target.observed == null)
124 {
125 EditorUtility.DisplayDialog("Warning", "Setting the synchronization option only makes sense if you observe something.", "OK, I will fix it.");
126 }
127 }*/
128
129 DrawSpecificTypeSerializationOptions();
130
131 GUI.color = Color.white;
132 DrawObservedComponentsList();
133
134 // Cleanup: save and fix look
135 if (GUI.changed)
136 {
137 EditorUtility.SetDirty(m_Target);
138 PhotonViewHandler.HierarchyChange(); // TODO: check if needed
139 }
140
141 GUI.color = Color.white;
142 EditorGUIUtility.LookLikeControls();
143 }
File name: PhotonViewInspector.cs
Copy
209 void DrawOldObservedItem()
210 {
211 EditorGUILayout.BeginHorizontal();
212
213 // Using a lower version then 3.4? Remove the TRUE in the next line to fix an compile error
214 string typeOfObserved = string.Empty;
215 if( m_Target.observed != null )
216 {
217 int firstBracketPos = m_Target.observed.ToString().LastIndexOf( '(' );
218 if( firstBracketPos > 0 )
219 {
220 typeOfObserved = m_Target.observed.ToString().Substring( firstBracketPos );
221 }
222 }
223
224
225 Component componenValue = (Component)EditorGUILayout.ObjectField( "Observe: " + typeOfObserved, m_Target.observed, typeof( Component ), true );
226 if( m_Target.observed != componenValue )
227 {
228 if( m_Target.observed == null )
229 {
230 m_Target.synchronization = ViewSynchronization.UnreliableOnChange; // if we didn't observe anything yet. use unreliable on change as default
231 }
232 if( componenValue == null )
233 {
234 m_Target.synchronization = ViewSynchronization.Off;
235 }
236
237 m_Target.observed = componenValue;
238 }
239
240 EditorGUILayout.EndHorizontal();
241 }
File name: PhotonViewInspector.cs
Copy
258 void DrawObservedComponentsList()
259 {
260 GUILayout.Space( 5 );
261 SerializedProperty listProperty = serializedObject.FindProperty( "ObservedComponents" );
262
263 if( listProperty == null )
264 {
265 return;
266 }
267
268 float containerElementHeight = 22;
269 float containerHeight = listProperty.arraySize * containerElementHeight;
270
271 bool isOpen = PhotonGUI.ContainerHeaderFoldout( "Observed Components (" + GetObservedComponentsCount() + ")", serializedObject.FindProperty( "ObservedComponentsFoldoutOpen" ).boolValue );
272 serializedObject.FindProperty( "ObservedComponentsFoldoutOpen" ).boolValue = isOpen;
273
274 if( isOpen == false )
275 {
276 containerHeight = 0;
277 }
278
279 //Texture2D statsIcon = AssetDatabase.LoadAssetAtPath( "Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewStats.png", typeof( Texture2D ) ) as Texture2D;
280
281 Rect containerRect = PhotonGUI.ContainerBody( containerHeight );
282 bool wasObservedComponentsEmpty = m_Target.ObservedComponents.FindAll( item => item != null ).Count == 0;
283 if( isOpen == true )
284 {
285 for( int i = 0; i < listProperty.arraySize; ++i )
286 {
287 Rect elementRect = new Rect( containerRect.xMin, containerRect.yMin + containerElementHeight * i, containerRect.width, containerElementHeight );
288 {
289 Rect texturePosition = new Rect( elementRect.xMin + 6, elementRect.yMin + elementRect.height / 2f - 1, 9, 5 );
290 ReorderableListResources.DrawTexture( texturePosition, ReorderableListResources.texGrabHandle );
291
292 Rect propertyPosition = new Rect( elementRect.xMin + 20, elementRect.yMin + 3, elementRect.width - 45, 16 );
293 EditorGUI.PropertyField( propertyPosition, listProperty.GetArrayElementAtIndex( i ), new GUIContent() );
294
295 //Debug.Log( listProperty.GetArrayElementAtIndex( i ).objectReferenceValue.GetType() );
296 //Rect statsPosition = new Rect( propertyPosition.xMax + 7, propertyPosition.yMin, statsIcon.width, statsIcon.height );
297 //ReorderableListResources.DrawTexture( statsPosition, statsIcon );
298
299 Rect removeButtonRect = new Rect( elementRect.xMax - PhotonGUI.DefaultRemoveButtonStyle.fixedWidth,
300 elementRect.yMin + 2,
301 PhotonGUI.DefaultRemoveButtonStyle.fixedWidth,
302 PhotonGUI.DefaultRemoveButtonStyle.fixedHeight );
303
304 GUI.enabled = listProperty.arraySize > 1;
305 if( GUI.Button( removeButtonRect, new GUIContent( ReorderableListResources.texRemoveButton ), PhotonGUI.DefaultRemoveButtonStyle ) )
306 {
307 listProperty.DeleteArrayElementAtIndex( i );
308 }
309 GUI.enabled = true;
310
311 if( i < listProperty.arraySize - 1 )
312 {
313 texturePosition = new Rect( elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, 1 );
314 PhotonGUI.DrawSplitter( texturePosition );
315 }
316 }
317 }
318 }
319
320 if( PhotonGUI.AddButton() )
321 {
322 listProperty.InsertArrayElementAtIndex( Mathf.Max( 0, listProperty.arraySize - 1 ) );
323 }
324
325 serializedObject.ApplyModifiedProperties();
326
327 bool isObservedComponentsEmpty = m_Target.ObservedComponents.FindAll( item => item != null ).Count == 0;
328
329 if( wasObservedComponentsEmpty == true && isObservedComponentsEmpty == false && m_Target.synchronization == ViewSynchronization.Off )
330 {
331 m_Target.synchronization = ViewSynchronization.UnreliableOnChange;
332 EditorUtility.SetDirty( m_Target );
333 serializedObject.Update();
334 }
335
336 if( wasObservedComponentsEmpty == false && isObservedComponentsEmpty == true )
337 {
338 m_Target.synchronization = ViewSynchronization.Off;
339 EditorUtility.SetDirty( m_Target );
340 serializedObject.Update();
341 }
342
343 }
File name: NetworkingPeer.cs
Copy
3147 public void RunViewUpdate()
3148 {
3149 if (!PhotonNetwork.connected || PhotonNetwork.offlineMode)
3150 {
3151 return;
3152 }
3153
3154 if (this.mActors == null ||
3155#if !PHOTON_DEVELOP
3156 this.mActors.Count <= 1
3157#endif
3158 )
3159 {
3160 return; // No need to send OnSerialize messages (these are never buffered anyway)
3161 }
3162
3163 dataPerGroupReliable.Clear();
3164 dataPerGroupUnreliable.Clear();
3165
3166 /* Format of the data hashtable:
3167 * Hasthable dataPergroup*
3168 * [(byte)0] = this.ServerTimeInMilliSeconds;
3169 * OPTIONAL: [(byte)1] = currentLevelPrefix;
3170 * + data
3171 */
3172
3173 foreach (KeyValuePair
3174 {
3175 PhotonView view = kvp.Value;
3176
3177 if (view.synchronization != ViewSynchronization.Off)
3178 {
3179 // Fetch all sending photonViews
3180 if (view.isMine)
3181 {
3182 #if UNITY_2_6_1 || UNITY_2_6 || UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5
3183 if (!view.gameObject.active)
3184 {
3185 continue; // Only on actives
3186 }
3187 #else
3188 if (!view.gameObject.activeInHierarchy)
3189 {
3190 continue; // Only on actives
3191 }
3192 #endif
3193
3194 if (this.blockSendingGroups.Contains(view.group))
3195 {
3196 continue; // Block sending on this group
3197 }
3198
3199 // Run it trough its OnSerialize
3200 Hashtable evData = this.OnSerializeWrite(view);
3201 if (evData == null)
3202 {
3203 continue;
3204 }
3205
3206 if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed || view.mixedModeIsReliable)
3207 {
3208 if (!evData.ContainsKey((byte)1) && !evData.ContainsKey((byte)2))
3209 {
3210 // Everything has been removed by compression, nothing to send
3211 }
3212 else
3213 {
3214 if (!dataPerGroupReliable.ContainsKey(view.group))
3215 {
3216 dataPerGroupReliable[view.group] = new Hashtable();
3217 dataPerGroupReliable[view.group][(byte)0] = this.ServerTimeInMilliSeconds;
3218 if (currentLevelPrefix >= 0)
3219 {
3220 dataPerGroupReliable[view.group][(byte)1] = this.currentLevelPrefix;
3221 }
3222 }
3223 Hashtable groupHashtable = dataPerGroupReliable[view.group];
3224 groupHashtable.Add((short)groupHashtable.Count, evData);
3225 }
3226 }
3227 else
3228 {
3229 if (!dataPerGroupUnreliable.ContainsKey(view.group))
3230 {
3231 dataPerGroupUnreliable[view.group] = new Hashtable();
3232 dataPerGroupUnreliable[view.group][(byte)0] = this.ServerTimeInMilliSeconds;
3233 if (currentLevelPrefix >= 0)
3234 {
3235 dataPerGroupUnreliable[view.group][(byte)1] = this.currentLevelPrefix;
3236 }
3237 }
3238 Hashtable groupHashtable = dataPerGroupUnreliable[view.group];
3239 groupHashtable.Add((short)groupHashtable.Count, evData);
3240 }
3241 }
3242 else
3243 {
3244 // Debug.Log(" NO OBS on " + view.name + " " + view.owner);
3245 }
3246 }
3247 else
3248 {
3249 }
3250 }
3251
3252 //Send the messages: every group is send in it's own message and unreliable and reliable are split as well
3253 RaiseEventOptions options = new RaiseEventOptions();
3254
3255#if PHOTON_DEVELOP
3256 options.Receivers = ReceiverGroup.All;
3257#endif
3258
3259 foreach (KeyValuePair
3260 {
3261 options.InterestGroup = (byte)kvp.Key;
3262 this.OpRaiseEvent(PunEvent.SendSerializeReliable, kvp.Value, true, options);
3263 }
3264 foreach (KeyValuePair
3265 {
3266 options.InterestGroup = (byte)kvp.Key;
3267 this.OpRaiseEvent(PunEvent.SendSerialize, kvp.Value, false, options);
3268 }
3269 }
File name: NetworkingPeer.cs
Copy
3271 // calls OnPhotonSerializeView (through ExecuteOnSerialize)
3273 private Hashtable OnSerializeWrite(PhotonView view)
3274 {
3275 PhotonStream pStream = new PhotonStream( true, null );
3276 PhotonMessageInfo info = new PhotonMessageInfo( this.mLocalActor, this.ServerTimeInMilliSeconds, view );
3277
3278 // each view creates a list of values that should be sent
3279 view.SerializeView( pStream, info );
3280
3281 if( pStream.Count == 0 )
3282 {
3283 return null;
3284 }
3285
3286 object[] dataArray = pStream.data.ToArray();
3287
3288 if (view.synchronization == ViewSynchronization.UnreliableOnChange)
3289 {
3290 if (AlmostEquals(dataArray, view.lastOnSerializeDataSent))
3291 {
3292 if (view.mixedModeIsReliable)
3293 {
3294 return null;
3295 }
3296
3297 view.mixedModeIsReliable = true;
3298 view.lastOnSerializeDataSent = dataArray;
3299 }
3300 else
3301 {
3302 view.mixedModeIsReliable = false;
3303 view.lastOnSerializeDataSent = dataArray;
3304 }
3305 }
3306
3307 // EVDATA:
3308 // 0=View ID (an int, never compressed cause it's not in the data)
3309 // 1=data of observed type (different per type of observed object)
3310 // 2=compressed data (in this case, key 1 is empty)
3311 // 3=list of values that are actually null (if something was changed but actually IS null)
3312 Hashtable evData = new Hashtable();
3313 evData[(byte)0] = (int)view.viewID;
3314 evData[(byte)1] = dataArray; // this is the actual data (script or observed object)
3315
3316
3317 if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed)
3318 {
3319 // compress content of data set (by comparing to view.lastOnSerializeDataSent)
3320 // the "original" dataArray is NOT modified by DeltaCompressionWrite
3321 // if something was compressed, the evData key 2 and 3 are used (see above)
3322 bool somethingLeftToSend = this.DeltaCompressionWrite(view, evData);
3323
3324 // buffer the full data set (for next compression)
3325 view.lastOnSerializeDataSent = dataArray;
3326
3327 if (!somethingLeftToSend)
3328 {
3329 return null;
3330 }
3331 }
3332
3333 return evData;
3334 }
File name: NetworkingPeer.cs
Copy
3339 private void OnSerializeRead(Hashtable data, PhotonPlayer sender, int networkTime, short correctPrefix)
3340 {
3341 // read view ID from key (byte)0: a int-array (PUN 1.17++)
3342 int viewID = (int)data[(byte)0];
3343
3344
3345 PhotonView view = this.GetPhotonView(viewID);
3346 if (view == null)
3347 {
3348 Debug.LogWarning("Received OnSerialization for view ID " + viewID + ". We have no such PhotonView! Ignored this if you're leaving a room. State: " + this.State);
3349 return;
3350 }
3351
3352 if (view.prefix > 0 && correctPrefix != view.prefix)
3353 {
3354 Debug.LogError("Received OnSerialization for view ID " + viewID + " with prefix " + correctPrefix + ". Our prefix is " + view.prefix);
3355 return;
3356 }
3357
3358 // SetReceiving filtering
3359 if (view.group != 0 && !this.allowedReceivingGroups.Contains(view.group))
3360 {
3361 return; // Ignore group
3362 }
3363
3364
3365 if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed)
3366 {
3367 if (!this.DeltaCompressionRead(view, data))
3368 {
3369 // Skip this packet as we haven't got received complete-copy of this view yet.
3370 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
3371 Debug.Log("Skipping packet for " + view.name + " [" + view.viewID + "] as we haven't received a full packet for delta compression yet. This is OK if it happens for the first few frames after joining a game.");
3372 return;
3373 }
3374
3375 // store last received for delta-compression usage
3376 view.lastOnSerializeDataReceived = data[(byte)1] as object[];
3377 }
3378
3379 if (sender.ID != view.ownerId)
3380 {
3381 if (!view.isSceneView || !sender.isMasterClient)
3382 {
3383 // obviously the owner changed and we didn't yet notice.
3384 Debug.Log("Adjusting owner to sender of updates. From: " + view.ownerId + " to: " + sender.ID);
3385 view.ownerId = sender.ID;
3386 }
3387 }
3388
3389 object[] contents = data[(byte)1] as object[];
3390 PhotonStream pStream = new PhotonStream(false, contents);
3391 PhotonMessageInfo info = new PhotonMessageInfo(sender, networkTime, view);
3392
3393 view.DeserializeView( pStream, info );
3394 }
ViewSynchronization 122 lượt xem
Gõ tìm kiếm nhanh...