NetworkingPeer
How do I use Networking Peer
Below are practical examples compiled from projects for learning and reference purposes
Featured Snippets
File name: WorkerMenu.cs
Copy
234 public void OnFailedToConnectToPhoton(object parameters)
235 {
236 this.connectFailed = true;
237 Debug.Log("OnFailedToConnectToPhoton. StatusCode: " + parameters + " ServerAddress: " + PhotonNetwork.networkingPeer.ServerAddress);
238 }
File name: CustomTypes.cs
Copy
160 private static object DeserializePhotonPlayer(MemoryStream inStream, short length)
161 {
162 int ID;
163 lock (memPlayer)
164 {
165 inStream.Read(memPlayer, 0, length);
166 int off = 0;
167 Protocol.Deserialize(out ID, memPlayer, ref off);
168 }
169
170 if (PhotonNetwork.networkingPeer.mActors.ContainsKey(ID))
171 {
172 return PhotonNetwork.networkingPeer.mActors[ID];
173 }
174 else
175 {
176 return null;
177 }
178 }
File name: NetworkingPeer.cs
Copy
185 public NetworkingPeer(IPhotonPeerListener listener, string playername, ConnectionProtocol connectionProtocol) : base(listener, connectionProtocol)
186 {
187 #if !UNITY_EDITOR && (UNITY_WINRT)
188 // this automatically uses a separate assembly-file with Win8-style Socket usage (not possible in Editor)
189 Debug.LogWarning("Using PingWindowsStore");
190 PhotonHandler.PingImplementation = typeof(PingWindowsStore); // but for ping, we have to set the implementation explicitly to Win 8 Store/Phone
191 #endif
192
193 #pragma warning disable 0162 // the library variant defines if we should use PUN's SocketUdp variant (at all)
194 if (PhotonPeer.NoSocket)
195 {
196 #if !UNITY_EDITOR && (UNITY_PS3 || UNITY_ANDROID)
197 Debug.Log("Using class SocketUdpNativeDynamic");
198 this.SocketImplementation = typeof(SocketUdpNativeDynamic);
199 PhotonHandler.PingImplementation = typeof(PingNativeDynamic);
200 #elif !UNITY_EDITOR && UNITY_IPHONE
201 Debug.Log("Using class SocketUdpNativeStatic");
202 this.SocketImplementation = typeof(SocketUdpNativeStatic);
203 PhotonHandler.PingImplementation = typeof(PingNativeStatic);
204 #elif !UNITY_EDITOR && (UNITY_WINRT)
205 // this automatically uses a separate assembly-file with Win8-style Socket usage (not possible in Editor)
206 #else
207 this.SocketImplementation = typeof (SocketUdp);
208 PhotonHandler.PingImplementation = typeof(PingMonoEditor);
209 #endif
210
211 if (this.SocketImplementation == null)
212 {
213 Debug.Log("No socket implementation set for 'NoSocket' assembly. Please contact Exit Games.");
214 }
215 }
216 #pragma warning restore 0162
217
218 if (PhotonHandler.PingImplementation == null)
219 {
220 PhotonHandler.PingImplementation = typeof(PingMono);
221 }
222
223 this.Listener = this;
224 this.lobby = TypedLobby.Default;
225 this.LimitOfUnreliableCommands = 40;
226
227 // don't set the field directly! the listener is passed on to other classes, which get updated by the property set method
228 this.externalListener = listener;
229 this.PlayerName = playername;
230 this.mLocalActor = new PhotonPlayer(true, -1, this.playername);
231 this.AddNewPlayer(this.mLocalActor.ID, this.mLocalActor);
232
233 // RPC shortcut lookup creation (from list of RPCs, which is updated by Editor scripts)
234 rpcShortcuts = new Dictionary
235 for (int index = 0; index < PhotonNetwork.PhotonServerSettings.RpcList.Count; index++)
236 {
237 var name = PhotonNetwork.PhotonServerSettings.RpcList[index];
238 rpcShortcuts[name] = index;
239 }
240
241 this.State = global::PeerState.PeerCreated;
242 }
File name: NetworkingPeer.cs
Copy
1016 public void OnOperationResponse(OperationResponse operationResponse)
1017 {
1018 if (PhotonNetwork.networkingPeer.State == global::PeerState.Disconnecting)
1019 {
1020 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1021 {
1022 Debug.Log("OperationResponse ignored while disconnecting. Code: " + operationResponse.OperationCode);
1023 }
1024 return;
1025 }
1026
1027 // extra logging for error debugging (helping developers with a bit of automated analysis)
1028 if (operationResponse.ReturnCode == 0)
1029 {
1030 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1031 Debug.Log(operationResponse.ToString());
1032 }
1033 else
1034 {
1035 if (operationResponse.ReturnCode == ErrorCode.OperationNotAllowedInCurrentState)
1036 {
1037 Debug.LogError("Operation " + operationResponse.OperationCode + " could not be executed (yet). Wait for state JoinedLobby or ConnectedToMaster and their callbacks before calling operations. WebRPCs need a server-side configuration. Enum OperationCode helps identify the operation.");
1038 }
1039 else if (operationResponse.ReturnCode == ErrorCode.WebHookCallFailed)
1040 {
1041 Debug.LogError("Operation " + operationResponse.OperationCode + " failed in a server-side plugin. Check the configuration in the Dashboard. Message from server-plugin: " + operationResponse.DebugMessage);
1042 }
1043 else if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1044 {
1045 Debug.LogError("Operation failed: " + operationResponse.ToStringFull() + " Server: " + this.server);
1046 }
1047 }
1048
1049 // use the "secret" or "token" whenever we get it. doesn't really matter if it's in AuthResponse.
1050 if (operationResponse.Parameters.ContainsKey(ParameterCode.Secret))
1051 {
1052 if (this.CustomAuthenticationValues == null)
1053 {
1054 this.CustomAuthenticationValues = new AuthenticationValues();
1055 // this.DebugReturn(DebugLevel.ERROR, "Server returned secret. Created CustomAuthenticationValues.");
1056 }
1057
1058 this.CustomAuthenticationValues.Secret = operationResponse[ParameterCode.Secret] as string;
1059 }
1060
1061 switch (operationResponse.OperationCode)
1062 {
1063 case OperationCode.Authenticate:
1064 {
1065 // PeerState oldState = this.State;
1066
1067 if (operationResponse.ReturnCode != 0)
1068 {
1069 if (operationResponse.ReturnCode == ErrorCode.InvalidOperationCode)
1070 {
1071 Debug.LogError(string.Format("If you host Photon yourself, make sure to start the 'Instance LoadBalancing' "+ this.ServerAddress));
1072 }
1073 else if (operationResponse.ReturnCode == ErrorCode.InvalidAuthentication)
1074 {
1075 Debug.LogError(string.Format("The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account."));
1076 SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication);
1077 }
1078 else if (operationResponse.ReturnCode == ErrorCode.CustomAuthenticationFailed)
1079 {
1080 Debug.LogError(string.Format("Custom Authentication failed (either due to user-input or configuration or AuthParameter string format). Calling: OnCustomAuthenticationFailed()"));
1081 SendMonoMessage(PhotonNetworkingMessage.OnCustomAuthenticationFailed, operationResponse.DebugMessage);
1082 }
1083 else
1084 {
1085 Debug.LogError(string.Format("Authentication failed: '{0}' Code: {1}", operationResponse.DebugMessage, operationResponse.ReturnCode));
1086 }
1087
1088 this.State = global::PeerState.Disconnecting;
1089 this.Disconnect();
1090
1091 if (operationResponse.ReturnCode == ErrorCode.MaxCcuReached)
1092 {
1093 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1094 Debug.LogWarning(string.Format("Currently, the limit of users is reached for this title. Try again later. Disconnecting"));
1095 SendMonoMessage(PhotonNetworkingMessage.OnPhotonMaxCccuReached);
1096 SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.MaxCcuReached);
1097 }
1098 else if (operationResponse.ReturnCode == ErrorCode.InvalidRegion)
1099 {
1100 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1101 Debug.LogError(string.Format("The used master server address is not available with the subscription currently used. Got to Photon Cloud Dashboard or change URL. Disconnecting."));
1102 SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.InvalidRegion);
1103 }
1104 else if (operationResponse.ReturnCode == ErrorCode.AuthenticationTicketExpired)
1105 {
1106 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1107 Debug.LogError(string.Format("The authentication ticket expired. You need to connect (and authenticate) again. Disconnecting."));
1108 SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.AuthenticationTicketExpired);
1109 }
1110 break;
1111 }
1112 else
1113 {
1114 if (this.server == ServerConnection.NameServer)
1115 {
1116 // on the NameServer, authenticate returns the MasterServer address for a region and we hop off to there
1117 this.MasterServerAddress = operationResponse[ParameterCode.Address] as string;
1118 this.DisconnectToReconnect();
1119 }
1120 else if (this.server == ServerConnection.MasterServer)
1121 {
1122 if (PhotonNetwork.autoJoinLobby)
1123 {
1124 this.State = global::PeerState.Authenticated;
1125 this.OpJoinLobby(this.lobby);
1126 }
1127 else
1128 {
1129 this.State = global::PeerState.ConnectedToMaster;
1130 NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnConnectedToMaster);
1131 }
1132 }
1133 else if (this.server == ServerConnection.GameServer)
1134 {
1135 this.State = global::PeerState.Joining;
1136
1137 if (this.mLastJoinType == JoinType.JoinGame || this.mLastJoinType == JoinType.JoinRandomGame || this.mLastJoinType == JoinType.JoinOrCreateOnDemand)
1138 {
1139 // if we just "join" the game, do so. if we wanted to "create the room on demand", we have to send this to the game server as well.
1140 this.OpJoinRoom(this.mRoomToGetInto.name, this.mRoomOptionsForCreate, this.mRoomToEnterLobby, this.mLastJoinType == JoinType.JoinOrCreateOnDemand);
1141 }
1142 else if (this.mLastJoinType == JoinType.CreateGame)
1143 {
1144 // on the game server, we have to apply the room properties that were chosen for creation of the room, so we use this.mRoomToGetInto
1145 this.OpCreateGame(this.mRoomToGetInto.name, this.mRoomOptionsForCreate, this.mRoomToEnterLobby);
1146 }
1147
1148 break;
1149 }
1150 }
1151 break;
1152 }
1153
1154 case OperationCode.GetRegions:
1155 // Debug.Log("GetRegions returned: " + operationResponse.ToStringFull());
1156
1157 if (operationResponse.ReturnCode == ErrorCode.InvalidAuthentication)
1158 {
1159 Debug.LogError(string.Format("The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account."));
1160 SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication);
1161
1162 this.State = global::PeerState.Disconnecting;
1163 this.Disconnect();
1164 return;
1165 }
1166
1167 string[] regions = operationResponse[ParameterCode.Region] as string[];
1168 string[] servers = operationResponse[ParameterCode.Address] as string[];
1169
1170 if (regions == null || servers == null || regions.Length != servers.Length)
1171 {
1172 Debug.LogError("The region arrays from Name Server are not ok. Must be non-null and same length.");
1173 break;
1174 }
1175
1176 this.AvailableRegions = new List
1177 for (int i = 0; i < regions.Length; i++)
1178 {
1179 string regionCodeString = regions[i];
1180 if (string.IsNullOrEmpty(regionCodeString))
1181 {
1182 continue;
1183 }
1184 regionCodeString = regionCodeString.ToLower();
1185
1186 CloudRegionCode code = Region.Parse(regionCodeString);
1187 this.AvailableRegions.Add(new Region() { Code = code, HostAndPort = servers[i] });
1188 }
1189
1190 // PUN assumes you fetch the name-server's list of regions to ping them
1191 if (PhotonNetwork.PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion)
1192 {
1193 PhotonHandler.PingAvailableRegionsAndConnectToBest();
1194 }
1195 break;
1196
1197 case OperationCode.CreateGame:
1198 {
1199 if (this.server == ServerConnection.GameServer)
1200 {
1201 this.GameEnteredOnGameServer(operationResponse);
1202 }
1203 else
1204 {
1205 if (operationResponse.ReturnCode != 0)
1206 {
1207 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1208 Debug.LogWarning(string.Format("CreateRoom failed, client stays on masterserver: {0}.", operationResponse.ToStringFull()));
1209
1210 SendMonoMessage(PhotonNetworkingMessage.OnPhotonCreateRoomFailed);
1211 break;
1212 }
1213
1214 string gameID = (string) operationResponse[ParameterCode.RoomName];
1215 if (!string.IsNullOrEmpty(gameID))
1216 {
1217 // is only sent by the server's response, if it has not been
1218 // sent with the client's request before!
1219 this.mRoomToGetInto.name = gameID;
1220 }
1221
1222 this.mGameserver = (string)operationResponse[ParameterCode.Address];
1223 this.DisconnectToReconnect();
1224 }
1225
1226 break;
1227 }
1228
1229 case OperationCode.JoinGame:
1230 {
1231 if (this.server != ServerConnection.GameServer)
1232 {
1233 if (operationResponse.ReturnCode != 0)
1234 {
1235 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1236 Debug.Log(string.Format("JoinRoom failed (room maybe closed by now). Client stays on masterserver: {0}. State: {1}", operationResponse.ToStringFull(), this.State));
1237
1238 SendMonoMessage(PhotonNetworkingMessage.OnPhotonJoinRoomFailed);
1239 break;
1240 }
1241
1242 this.mGameserver = (string)operationResponse[ParameterCode.Address];
1243 this.DisconnectToReconnect();
1244 }
1245 else
1246 {
1247 this.GameEnteredOnGameServer(operationResponse);
1248 }
1249
1250 break;
1251 }
1252
1253 case OperationCode.JoinRandomGame:
1254 {
1255 // happens only on master. on gameserver, this is a regular join (we don't need to find a random game again)
1256 // the operation OpJoinRandom either fails (with returncode 8) or returns game-to-join information
1257 if (operationResponse.ReturnCode != 0)
1258 {
1259 if (operationResponse.ReturnCode == ErrorCode.NoRandomMatchFound)
1260 {
1261 if (PhotonNetwork.logLevel >= PhotonLogLevel.Full)
1262 Debug.Log("JoinRandom failed: No open game. Calling: OnPhotonRandomJoinFailed() and staying on master server.");
1263 }
1264 else if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1265 {
1266 Debug.LogWarning(string.Format("JoinRandom failed: {0}.", operationResponse.ToStringFull()));
1267 }
1268
1269 SendMonoMessage(PhotonNetworkingMessage.OnPhotonRandomJoinFailed, operationResponse.ReturnCode, operationResponse.DebugMessage);
1270 break;
1271 }
1272
1273 string roomName = (string)operationResponse[ParameterCode.RoomName];
1274 this.mRoomToGetInto.name = roomName;
1275 this.mGameserver = (string)operationResponse[ParameterCode.Address];
1276 this.DisconnectToReconnect();
1277 break;
1278 }
1279
1280 case OperationCode.JoinLobby:
1281 this.State = global::PeerState.JoinedLobby;
1282 this.insideLobby = true;
1283 SendMonoMessage(PhotonNetworkingMessage.OnJoinedLobby);
1284
1285 // this.mListener.joinLobbyReturn();
1286 break;
1287 case OperationCode.LeaveLobby:
1288 this.State = global::PeerState.Authenticated;
1289 this.LeftLobbyCleanup(); // will set insideLobby = false
1290 break;
1291
1292 case OperationCode.Leave:
1293 this.DisconnectToReconnect();
1294 break;
1295
1296 case OperationCode.SetProperties:
1297 // this.mListener.setPropertiesReturn(returnCode, debugMsg);
1298 break;
1299
1300 case OperationCode.GetProperties:
1301 {
1302 Hashtable actorProperties = (Hashtable)operationResponse[ParameterCode.PlayerProperties];
1303 Hashtable gameProperties = (Hashtable)operationResponse[ParameterCode.GameProperties];
1304 this.ReadoutProperties(gameProperties, actorProperties, 0);
1305
1306 // RemoveByteTypedPropertyKeys(actorProperties, false);
1307 // RemoveByteTypedPropertyKeys(gameProperties, false);
1308 // this.mListener.getPropertiesReturn(gameProperties, actorProperties, returnCode, debugMsg);
1309 break;
1310 }
1311
1312 case OperationCode.RaiseEvent:
1313 // this usually doesn't give us a result. only if the caching is affected the server will send one.
1314 break;
1315
1316 case OperationCode.FindFriends:
1317 bool[] onlineList = operationResponse[ParameterCode.FindFriendsResponseOnlineList] as bool[];
1318 string[] roomList = operationResponse[ParameterCode.FindFriendsResponseRoomIdList] as string[];
1319
1320 if (onlineList != null && roomList != null && this.friendListRequested != null && onlineList.Length == this.friendListRequested.Length)
1321 {
1322 List
1323 for (int index = 0; index < this.friendListRequested.Length; index++)
1324 {
1325 FriendInfo friend = new FriendInfo();
1326 friend.Name = this.friendListRequested[index];
1327 friend.Room = roomList[index];
1328 friend.IsOnline = onlineList[index];
1329 friendList.Insert(index, friend);
1330 }
1331 PhotonNetwork.Friends = friendList;
1332 }
1333 else
1334 {
1335 // any of the lists is null and shouldn't. print a error
1336 Debug.LogError("FindFriends failed to apply the result, as a required value wasn't provided or the friend list length differed from result.");
1337 }
1338
1339 this.friendListRequested = null;
1340 this.isFetchingFriends = false;
1341 this.friendListTimestamp = Environment.TickCount;
1342 if (this.friendListTimestamp == 0)
1343 {
1344 this.friendListTimestamp = 1; // makes sure the timestamp is not accidentally 0
1345 }
1346
1347 SendMonoMessage(PhotonNetworkingMessage.OnUpdatedFriendList);
1348 break;
1349
1350 case OperationCode.WebRpc:
1351 SendMonoMessage(PhotonNetworkingMessage.OnWebRpcResponse, operationResponse);
1352 break;
1353
1354 default:
1355 Debug.LogWarning(string.Format("OperationResponse unhandled: {0}", operationResponse.ToString()));
1356 break;
1357 }
1358
1359 this.externalListener.OnOperationResponse(operationResponse);
1360 }
File name: NetworkingPeer.cs
Copy
2279 internal GameObject DoInstantiate(Hashtable evData, PhotonPlayer photonPlayer, GameObject resourceGameObject)
2280 {
2281 // some values always present:
2282 string prefabName = (string)evData[(byte)0];
2283 int serverTime = (int)evData[(byte)6];
2284 int instantiationId = (int)evData[(byte)7];
2285
2286 Vector3 position;
2287 if (evData.ContainsKey((byte)1))
2288 {
2289 position = (Vector3)evData[(byte)1];
2290 }
2291 else
2292 {
2293 position = Vector3.zero;
2294 }
2295
2296 Quaternion rotation = Quaternion.identity;
2297 if (evData.ContainsKey((byte)2))
2298 {
2299 rotation = (Quaternion)evData[(byte)2];
2300 }
2301
2302 int group = 0;
2303 if (evData.ContainsKey((byte)3))
2304 {
2305 group = (int)evData[(byte)3];
2306 }
2307
2308 short objLevelPrefix = 0;
2309 if (evData.ContainsKey((byte)8))
2310 {
2311 objLevelPrefix = (short)evData[(byte)8];
2312 }
2313
2314 int[] viewsIDs;
2315 if (evData.ContainsKey((byte)4))
2316 {
2317 viewsIDs = (int[])evData[(byte)4];
2318 }
2319 else
2320 {
2321 viewsIDs = new int[1] { instantiationId };
2322 }
2323
2324 object[] incomingInstantiationData;
2325 if (evData.ContainsKey((byte)5))
2326 {
2327 incomingInstantiationData = (object[])evData[(byte)5];
2328 }
2329 else
2330 {
2331 incomingInstantiationData = null;
2332 }
2333
2334 // SetReceiving filtering
2335 if (group != 0 && !this.allowedReceivingGroups.Contains(group))
2336 {
2337 return null; // Ignore group
2338 }
2339
2340 // load prefab, if it wasn't loaded before (calling methods might do this)
2341 if (resourceGameObject == null)
2342 {
2343 if (!NetworkingPeer.UsePrefabCache || !NetworkingPeer.PrefabCache.TryGetValue(prefabName, out resourceGameObject))
2344 {
2345 resourceGameObject = (GameObject)Resources.Load(prefabName, typeof(GameObject));
2346 if (NetworkingPeer.UsePrefabCache)
2347 {
2348 NetworkingPeer.PrefabCache.Add(prefabName, resourceGameObject);
2349 }
2350 }
2351
2352 if (resourceGameObject == null)
2353 {
2354 Debug.LogError("PhotonNetwork error: Could not Instantiate the prefab [" + prefabName + "]. Please verify you have this gameobject in a Resources folder.");
2355 return null;
2356 }
2357 }
2358
2359 // now modify the loaded "blueprint" object before it becomes a part of the scene (by instantiating it)
2360 PhotonView[] resourcePVs = resourceGameObject.GetPhotonViewsInChildren();
2361 if (resourcePVs.Length != viewsIDs.Length)
2362 {
2363 throw new Exception("Error in Instantiation! The resource's PhotonView count is not the same as in incoming data.");
2364 }
2365
2366 for (int i = 0; i < viewsIDs.Length; i++)
2367 {
2368 // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it's set below
2369 // so we only set the viewID and instantiationId now. the instantiationData can be fetched
2370 resourcePVs[i].viewID = viewsIDs[i];
2371 resourcePVs[i].prefix = objLevelPrefix;
2372 resourcePVs[i].instantiationId = instantiationId;
2373 resourcePVs[i].isRuntimeInstantiated = true;
2374 }
2375
2376 this.StoreInstantiationData(instantiationId, incomingInstantiationData);
2377
2378 // load the resource and set it's values before instantiating it:
2379 GameObject go = (GameObject)GameObject.Instantiate(resourceGameObject, position, rotation);
2380
2381 for (int i = 0; i < viewsIDs.Length; i++)
2382 {
2383 // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it's set below
2384 // so we only set the viewID and instantiationId now. the instantiationData can be fetched
2385 resourcePVs[i].viewID = 0;
2386 resourcePVs[i].prefix = -1;
2387 resourcePVs[i].prefixBackup = -1;
2388 resourcePVs[i].instantiationId = -1;
2389 resourcePVs[i].isRuntimeInstantiated = false;
2390 }
2391
2392 this.RemoveInstantiationData(instantiationId);
2393
2394 // Send OnPhotonInstantiate callback to newly created GO.
2395 // GO will be enabled when instantiated from Prefab and it does not matter if the script is enabled or disabled.
2396 go.SendMessage(PhotonNetworkingMessage.OnPhotonInstantiate.ToString(), new PhotonMessageInfo(photonPlayer, serverTime, null), SendMessageOptions.DontRequireReceiver);
2397 return go;
2398 }
File name: NetworkingPeer.cs
Copy
3630 internal protected void LoadLevelIfSynced()
3631 {
3632 if (!PhotonNetwork.automaticallySyncScene || PhotonNetwork.isMasterClient || PhotonNetwork.room == null)
3633 {
3634 return;
3635 }
3636
3637 // check if "current level" is set in props
3638 if (!PhotonNetwork.room.customProperties.ContainsKey(NetworkingPeer.CurrentSceneProperty))
3639 {
3640 return;
3641 }
3642
3643 // if loaded level is not the one defined my master in props, load that level
3644 object sceneId = PhotonNetwork.room.customProperties[NetworkingPeer.CurrentSceneProperty];
3645 if (sceneId is int)
3646 {
3647 if (Application.loadedLevel != (int)sceneId)
3648 PhotonNetwork.LoadLevel((int)sceneId);
3649 }
3650 else if (sceneId is string)
3651 {
3652 if (Application.loadedLevelName != (string)sceneId)
3653 PhotonNetwork.LoadLevel((string)sceneId);
3654 }
3655 }
File name: NetworkingPeer.cs
Copy
3657 protected internal void SetLevelInPropsIfSynced(object levelId)
3658 {
3659 if (!PhotonNetwork.automaticallySyncScene || !PhotonNetwork.isMasterClient || PhotonNetwork.room == null)
3660 {
3661 return;
3662 }
3663 if (levelId == null)
3664 {
3665 Debug.LogError("Parameter levelId can't be null!");
3666 return;
3667 }
3668
3669 // check if "current level" is already set in props
3670 if (PhotonNetwork.room.customProperties.ContainsKey(NetworkingPeer.CurrentSceneProperty))
3671 {
3672 object levelIdInProps = PhotonNetwork.room.customProperties[NetworkingPeer.CurrentSceneProperty];
3673 if (levelIdInProps is int && Application.loadedLevel == (int)levelIdInProps)
3674 {
3675 return;
3676 }
3677 if (levelIdInProps is string && Application.loadedLevelName.Equals((string)levelIdInProps))
3678 {
3679 return;
3680 }
3681 }
3682
3683 // current level is not yet in props, so this client has to set it
3684 Hashtable setScene = new Hashtable();
3685 if (levelId is int) setScene[NetworkingPeer.CurrentSceneProperty] = (int)levelId;
3686 else if (levelId is string) setScene[NetworkingPeer.CurrentSceneProperty] = (string)levelId;
3687 else Debug.LogError("Parameter levelId must be int or string!");
3688
3689 PhotonNetwork.room.SetCustomProperties(setScene);
3690 this.SendOutgoingCommands(); // send immediately! because: in most cases the client will begin to load and not send for a while
3691 }
File name: PhotonHandler.cs
Copy
59 protected void Update()
60 {
61 if (PhotonNetwork.networkingPeer == null)
62 {
63 Debug.LogError("NetworkPeer broke!");
64 return;
65 }
66
67 if (PhotonNetwork.connectionStateDetailed == PeerState.PeerCreated || PhotonNetwork.connectionStateDetailed == PeerState.Disconnected || PhotonNetwork.offlineMode)
68 {
69 return;
70 }
71
72 // the messageQueue might be paused. in that case a thread will send acknowledgements only. nothing else to do here.
73 if (!PhotonNetwork.isMessageQueueRunning)
74 {
75 return;
76 }
77
78 bool doDispatch = true;
79 while (PhotonNetwork.isMessageQueueRunning && doDispatch)
80 {
81 // DispatchIncomingCommands() returns true of it found any command to dispatch (event, result or state change)
82 UnityEngine.Profiling.Profiler.BeginSample("DispatchIncomingCommands");
83 doDispatch = PhotonNetwork.networkingPeer.DispatchIncomingCommands();
84 UnityEngine.Profiling.Profiler.EndSample();
85 }
86
87 int currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000); // avoiding Environment.TickCount, which could be negative on long-running platforms
88 if (PhotonNetwork.isMessageQueueRunning && currentMsSinceStart > this.nextSendTickCountOnSerialize)
89 {
90 PhotonNetwork.networkingPeer.RunViewUpdate();
91 this.nextSendTickCountOnSerialize = currentMsSinceStart + this.updateIntervalOnSerialize;
92 this.nextSendTickCount = 0; // immediately send when synchronization code was running
93 }
94
95 currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000);
96 if (currentMsSinceStart > this.nextSendTickCount)
97 {
98 bool doSend = true;
99 while (PhotonNetwork.isMessageQueueRunning && doSend)
100 {
101 // Send all outgoing commands
102 UnityEngine.Profiling.Profiler.BeginSample("SendOutgoingCommands");
103 doSend = PhotonNetwork.networkingPeer.SendOutgoingCommands();
104 UnityEngine.Profiling.Profiler.EndSample();
105 }
106
107 this.nextSendTickCount = currentMsSinceStart + this.updateInterval;
108 }
109 }
File name: PhotonHandler.cs
Copy
112 protected void OnLevelWasLoaded(int level)
113 {
114 PhotonNetwork.networkingPeer.NewSceneLoaded();
115 PhotonNetwork.networkingPeer.SetLevelInPropsIfSynced(Application.loadedLevelName);
116 }
File name: PhotonHandler.cs
Copy
118 protected void OnJoinedRoom()
119 {
120 PhotonNetwork.networkingPeer.LoadLevelIfSynced();
121 }
Download file with original file name:NetworkingPeer
NetworkingPeer 124 lượt xem
Gõ tìm kiếm nhanh...