IDS
How do I use I D S
Below are practical examples compiled from projects for learning and reference purposes
Featured Snippets
File name: PhotonViewHandler.cs
Copy
25 internal static void HierarchyChange()
26 {
27 if (Application.isPlaying)
28 {
29 //Debug.Log("HierarchyChange ignored, while running.");
30 CheckSceneForStuckHandlers = true; // done once AFTER play mode.
31 return;
32 }
33
34 if (CheckSceneForStuckHandlers)
35 {
36 CheckSceneForStuckHandlers = false;
37 PhotonNetwork.InternalCleanPhotonMonoFromSceneIfStuck();
38 }
39
40 HashSet
41 HashSet
42 bool fixedSomeId = false;
43
44 //// the following code would be an option if we only checked scene objects (but we can check all PVs)
45 //PhotonView[] pvObjects = GameObject.FindSceneObjectsOfType(typeof(PhotonView)) as PhotonView[];
46 //Debug.Log("HierarchyChange. PV Count: " + pvObjects.Length);
47
48 string levelName = Application.loadedLevelName;
49 #if UNITY_EDITOR
50 levelName = System.IO.Path.GetFileNameWithoutExtension(EditorApplication.currentScene);
51 #endif
52 int minViewIdInThisScene = PunSceneSettings.MinViewIdForScene(levelName);
53 //Debug.Log("Level '" + Application.loadedLevelName + "' has a minimum ViewId of: " + minViewIdInThisScene);
54
55 PhotonView[] pvObjects = Resources.FindObjectsOfTypeAll(typeof(PhotonView)) as PhotonView[];
56
57 foreach (PhotonView view in pvObjects)
58 {
59 // first pass: fix prefabs to viewID 0 if they got a view number assigned (cause they should not have one!)
60 if (EditorUtility.IsPersistent(view.gameObject))
61 {
62 if (view.viewID != 0 || view.prefixBackup != -1 || view.instantiationId != -1)
63 {
64 Debug.LogWarning("PhotonView on persistent object being fixed (id and prefix must be 0). Was: " + view);
65 view.viewID = 0;
66 view.prefixBackup = -1;
67 view.instantiationId = -1;
68 EditorUtility.SetDirty(view);
69 fixedSomeId = true;
70 }
71 }
72 else
73 {
74 // keep all scene-instanced PVs for later re-check
75 pvInstances.Add(view);
76 }
77 }
78
79 Dictionary
80
81 // second pass: check all used-in-scene viewIDs for duplicate viewIDs (only checking anything non-prefab)
82 // scene-PVs must have user == 0 (scene/room) and a subId != 0
83 foreach (PhotonView view in pvInstances)
84 {
85 if (view.ownerId > 0)
86 {
87 Debug.Log("Re-Setting Owner ID of: " + view);
88 }
89 view.ownerId = 0; // simply make sure no owner is set (cause room always uses 0)
90 view.prefix = -1; // TODO: prefix could be settable via inspector per scene?!
91
92 if (view.viewID != 0)
93 {
94 if (view.viewID < minViewIdInThisScene || usedInstanceViewNumbers.Contains(view.viewID))
95 {
96 view.viewID = 0; // avoid duplicates and negative values by assigning 0 as (temporary) number to be fixed in next pass
97 }
98 else
99 {
100 usedInstanceViewNumbers.Add(view.viewID); // builds a list of currently used viewIDs
101
102 int instId = 0;
103 if (idPerObject.TryGetValue(view.gameObject, out instId))
104 {
105 view.instantiationId = instId;
106 }
107 else
108 {
109 view.instantiationId = view.viewID;
110 idPerObject[view.gameObject] = view.instantiationId;
111 }
112 }
113 }
114
115 }
116
117 // third pass: anything that's now 0 must get a new (not yet used) ID (starting at 0)
118 int lastUsedId = (minViewIdInThisScene > 0) ? minViewIdInThisScene - 1 : 0;
119
120 foreach (PhotonView view in pvInstances)
121 {
122 if (view.viewID == 0)
123 {
124 // Debug.LogWarning("setting scene ID: " + view.gameObject.name + " ID: " + view.subId.ID + " scene ID: " + view.GetSceneID() + " IsPersistent: " + EditorUtility.IsPersistent(view.gameObject) + " IsSceneViewIDFree: " + IsSceneViewIDFree(view.subId.ID, view));
125 int nextViewId = PhotonViewHandler.GetID(lastUsedId, usedInstanceViewNumbers);
126
127 view.viewID = nextViewId;
128
129 int instId = 0;
130 if (idPerObject.TryGetValue(view.gameObject, out instId))
131 {
132 Debug.Log("Set inst ID");
133 view.instantiationId = instId;
134 }
135 else
136 {
137 view.instantiationId = view.viewID;
138 idPerObject[view.gameObject] = nextViewId;
139 }
140
141 //// when using the Editor's serialization (view.subId in this case), this is not needed, it seems
142 //PrefabUtility.RecordPrefabInstancePropertyModifications(view);
143
144 lastUsedId = nextViewId;
145 EditorUtility.SetDirty(view);
146 fixedSomeId = true;
147 }
148 }
149
150
151 if (fixedSomeId)
152 {
153 //Debug.LogWarning("Some subId was adjusted."); // this log is only interesting for Exit Games
154 }
155 }
File name: PhotonViewHandler.cs
Copy
159 public static int GetID(int idOffset, HashSet160 {
161 while (idOffset < PhotonNetwork.MAX_VIEW_IDS)
162 {
163 idOffset++;
164 if (!usedInstanceViewNumbers.Contains(idOffset))
165 {
166 break;
167 }
168 }
169
170 return idOffset;
171 }
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: LoadbalancingPeer.cs
Copy
29 private readonly Dictionary31 public LoadbalancingPeer(IPhotonPeerListener listener, ConnectionProtocol protocolType) : base(listener, protocolType)
32 {
33 }
File name: NetworkingPeer.cs
Copy
459 private void LeftRoomCleanup()
460 {
461 bool wasInRoom = mRoomToGetInto != null;
462 // when leaving a room, we clean up depending on that room's settings.
463 bool autoCleanupSettingOfRoom = (this.mRoomToGetInto != null) ? this.mRoomToGetInto.autoCleanUp : PhotonNetwork.autoCleanUpPlayerObjects;
464
465 this.hasSwitchedMC = false;
466 this.mRoomToGetInto = null;
467 this.mActors = new Dictionary
468 this.mPlayerListCopy = new PhotonPlayer[0];
469 this.mOtherPlayerListCopy = new PhotonPlayer[0];
470 this.mMasterClient = null;
471 this.allowedReceivingGroups = new HashSet
472 this.blockSendingGroups = new HashSet
473 this.mGameList = new Dictionary
474 this.mGameListCopy = new RoomInfo[0];
475 this.isFetchingFriends = false;
476
477 this.ChangeLocalID(-1);
478
479 // Cleanup all network objects (all spawned PhotonViews, local and remote)
480 if (autoCleanupSettingOfRoom)
481 {
482 this.LocalCleanupAnythingInstantiated(true);
483 PhotonNetwork.manuallyAllocatedViewIds = new List
484 }
485
486 if (wasInRoom)
487 {
488 SendMonoMessage(PhotonNetworkingMessage.OnLeftRoom);
489 }
490 }
File name: NetworkingPeer.cs
Copy
495 protected internal void LocalCleanupAnythingInstantiated(bool destroyInstantiatedGameObjects)
496 {
497 if (tempInstantiationData.Count > 0)
498 {
499 Debug.LogWarning("It seems some instantiation is not completed, as instantiation data is used. You should make sure instantiations are paused when calling this method. Cleaning now, despite this.");
500 }
501
502 // Destroy GO's (if we should)
503 if (destroyInstantiatedGameObjects)
504 {
505 // Fill list with Instantiated objects
506 HashSet
507 foreach (PhotonView view in this.photonViewList.Values)
508 {
509 if (view.isRuntimeInstantiated)
510 {
511 instantiatedGos.Add(view.gameObject); // HashSet keeps each object only once
512 }
513 }
514
515 foreach (GameObject go in instantiatedGos)
516 {
517 this.RemoveInstantiatedGO(go, true);
518 }
519 }
520
521 // photonViewList is cleared of anything instantiated (so scene items are left inside)
522 // any other lists can be
523 this.tempInstantiationData.Clear(); // should be empty but to be safe we clear (no new list needed)
524 PhotonNetwork.lastUsedViewSubId = 0;
525 PhotonNetwork.lastUsedViewSubIdStatic = 0;
526 }
File name: NetworkingPeer.cs
Copy
1918 private void SendVacantViewIds()
1919 {
1920 Debug.Log("SendVacantViewIds()");
1921 List
1922 foreach (PhotonView view in this.photonViewList.Values)
1923 {
1924 if (!view.isOwnerActive)
1925 {
1926 vacantViews.Add(view.viewID);
1927 }
1928 }
1929
1930 Debug.Log("Sending vacant view IDs. Length: " + vacantViews.Count);
1931 //this.OpRaiseEvent(PunEvent.VacantViewIds, true, vacantViews.ToArray());
1932 this.OpRaiseEvent(PunEvent.VacantViewIds, vacantViews.ToArray(), true, null);
1933 }
File name: NetworkingPeer.cs
Copy
1962 public void ExecuteRPC(Hashtable rpcData, PhotonPlayer sender)
1963 {
1964 if (rpcData == null || !rpcData.ContainsKey((byte)0))
1965 {
1966 Debug.LogError("Malformed RPC; this should never occur. Content: " + SupportClass.DictionaryToString(rpcData));
1967 return;
1968 }
1969
1970 // ts: updated with "flat" event data
1971 int netViewID = (int)rpcData[(byte)0]; // LIMITS PHOTONVIEWS&PLAYERS
1972 int otherSidePrefix = 0; // by default, the prefix is 0 (and this is not being sent)
1973 if (rpcData.ContainsKey((byte)1))
1974 {
1975 otherSidePrefix = (short)rpcData[(byte)1];
1976 }
1977
1978 string inMethodName;
1979 if (rpcData.ContainsKey((byte)5))
1980 {
1981 int rpcIndex = (byte)rpcData[(byte)5]; // LIMITS RPC COUNT
1982 if (rpcIndex > PhotonNetwork.PhotonServerSettings.RpcList.Count - 1)
1983 {
1984 Debug.LogError("Could not find RPC with index: " + rpcIndex + ". Going to ignore! Check PhotonServerSettings.RpcList");
1985 return;
1986 }
1987 else
1988 {
1989 inMethodName = PhotonNetwork.PhotonServerSettings.RpcList[rpcIndex];
1990 }
1991 }
1992 else
1993 {
1994 inMethodName = (string)rpcData[(byte)3];
1995 }
1996
1997 object[] inMethodParameters = null;
1998 if (rpcData.ContainsKey((byte)4))
1999 {
2000 inMethodParameters = (object[])rpcData[(byte)4];
2001 }
2002
2003 if (inMethodParameters == null)
2004 {
2005 inMethodParameters = new object[0];
2006 }
2007
2008 PhotonView photonNetview = this.GetPhotonView(netViewID);
2009 if (photonNetview == null)
2010 {
2011 int viewOwnerId = netViewID/PhotonNetwork.MAX_VIEW_IDS;
2012 bool owningPv = (viewOwnerId == this.mLocalActor.ID);
2013 bool ownerSent = (viewOwnerId == sender.ID);
2014
2015 if (owningPv)
2016 {
2017 Debug.LogWarning("Received RPC \"" + inMethodName + "\" for viewID " + netViewID + " but this PhotonView does not exist! View was/is ours." + (ownerSent ? " Owner called." : " Remote called.") + " By: " + sender.ID);
2018 }
2019 else
2020 {
2021 Debug.LogWarning("Received RPC \"" + inMethodName + "\" for viewID " + netViewID + " but this PhotonView does not exist! Was remote PV." + (ownerSent ? " Owner called." : " Remote called.") + " By: " + sender.ID + " Maybe GO was destroyed but RPC not cleaned up.");
2022 }
2023 return;
2024 }
2025
2026 if (photonNetview.prefix != otherSidePrefix)
2027 {
2028 Debug.LogError(
2029 "Received RPC \"" + inMethodName + "\" on viewID " + netViewID + " with a prefix of " + otherSidePrefix
2030 + ", our prefix is " + photonNetview.prefix + ". The RPC has been ignored.");
2031 return;
2032 }
2033
2034 // Get method name
2035 if (inMethodName == string.Empty)
2036 {
2037 Debug.LogError("Malformed RPC; this should never occur. Content: " + SupportClass.DictionaryToString(rpcData));
2038 return;
2039 }
2040
2041 if (PhotonNetwork.logLevel >= PhotonLogLevel.Full)
2042 Debug.Log("Received RPC: " + inMethodName);
2043
2044
2045 // SetReceiving filtering
2046 if (photonNetview.group != 0 && !allowedReceivingGroups.Contains(photonNetview.group))
2047 {
2048 return; // Ignore group
2049 }
2050
2051 Type[] argTypes = new Type[0];
2052 if (inMethodParameters.Length > 0)
2053 {
2054 argTypes = new Type[inMethodParameters.Length];
2055 int i = 0;
2056 for (int index = 0; index < inMethodParameters.Length; index++)
2057 {
2058 object objX = inMethodParameters[index];
2059 if (objX == null)
2060 {
2061 argTypes[i] = null;
2062 }
2063 else
2064 {
2065 argTypes[i] = objX.GetType();
2066 }
2067
2068 i++;
2069 }
2070 }
2071
2072 int receivers = 0;
2073 int foundMethods = 0;
2074 MonoBehaviour[] mbComponents = photonNetview.GetComponents
2075 for (int componentsIndex = 0; componentsIndex < mbComponents.Length; componentsIndex++)
2076 {
2077 MonoBehaviour monob = mbComponents[componentsIndex];
2078 if (monob == null)
2079 {
2080 Debug.LogError("ERROR You have missing MonoBehaviours on your gameobjects!");
2081 continue;
2082 }
2083
2084 Type type = monob.GetType();
2085
2086 // Get [RPC] methods from cache
2087 List
2088 if (this.monoRPCMethodsCache.ContainsKey(type))
2089 {
2090 cachedRPCMethods = this.monoRPCMethodsCache[type];
2091 }
2092
2093 if (cachedRPCMethods == null)
2094 {
2095 List
2096
2097 this.monoRPCMethodsCache[type] = entries;
2098 cachedRPCMethods = entries;
2099 }
2100
2101 if (cachedRPCMethods == null)
2102 {
2103 continue;
2104 }
2105
2106 // Check cache for valid methodname+arguments
2107 for (int index = 0; index < cachedRPCMethods.Count; index++)
2108 {
2109 MethodInfo mInfo = cachedRPCMethods[index];
2110 if (mInfo.Name == inMethodName)
2111 {
2112 foundMethods++;
2113 ParameterInfo[] pArray = mInfo.GetParameters();
2114 if (pArray.Length == argTypes.Length)
2115 {
2116 // Normal, PhotonNetworkMessage left out
2117 if (this.CheckTypeMatch(pArray, argTypes))
2118 {
2119 receivers++;
2120 object result = mInfo.Invoke((object)monob, inMethodParameters);
2121 if (mInfo.ReturnType == typeof(IEnumerator))
2122 {
2123 monob.StartCoroutine((IEnumerator)result);
2124 }
2125 }
2126 }
2127 else if ((pArray.Length - 1) == argTypes.Length)
2128 {
2129 // Check for PhotonNetworkMessage being the last
2130 if (this.CheckTypeMatch(pArray, argTypes))
2131 {
2132 if (pArray[pArray.Length - 1].ParameterType == typeof(PhotonMessageInfo))
2133 {
2134 receivers++;
2135
2136 int sendTime = (int)rpcData[(byte)2];
2137 object[] deParamsWithInfo = new object[inMethodParameters.Length + 1];
2138 inMethodParameters.CopyTo(deParamsWithInfo, 0);
2139 deParamsWithInfo[deParamsWithInfo.Length - 1] = new PhotonMessageInfo(sender, sendTime, photonNetview);
2140
2141 object result = mInfo.Invoke((object)monob, deParamsWithInfo);
2142 if (mInfo.ReturnType == typeof(IEnumerator))
2143 {
2144 monob.StartCoroutine((IEnumerator)result);
2145 }
2146 }
2147 }
2148 }
2149 else if (pArray.Length == 1 && pArray[0].ParameterType.IsArray)
2150 {
2151 receivers++;
2152 object result = mInfo.Invoke((object)monob, new object[] { inMethodParameters });
2153 if (mInfo.ReturnType == typeof(IEnumerator))
2154 {
2155 monob.StartCoroutine((IEnumerator)result);
2156 }
2157 }
2158 }
2159 }
2160 }
2161
2162 // Error handling
2163 if (receivers != 1)
2164 {
2165 string argsString = string.Empty;
2166 for (int index = 0; index < argTypes.Length; index++)
2167 {
2168 Type ty = argTypes[index];
2169 if (argsString != string.Empty)
2170 {
2171 argsString += ", ";
2172 }
2173
2174 if (ty == null)
2175 {
2176 argsString += "null";
2177 }
2178 else
2179 {
2180 argsString += ty.Name;
2181 }
2182 }
2183
2184 if (receivers == 0)
2185 {
2186 if (foundMethods == 0)
2187 {
2188 Debug.LogError("PhotonView with ID " + netViewID + " has no method \"" + inMethodName + "\" marked with the [RPC](C#) or @RPC(JS) property! Args: " + argsString);
2189 }
2190 else
2191 {
2192 Debug.LogError("PhotonView with ID " + netViewID + " has no method \"" + inMethodName + "\" that takes " + argTypes.Length + " argument(s): " + argsString);
2193 }
2194 }
2195 else
2196 {
2197 Debug.LogError("PhotonView with ID " + netViewID + " has " + receivers + " methods \"" + inMethodName + "\" that takes " + argTypes.Length + " argument(s): " + argsString + ". Should be just one?");
2198 }
2199 }
2200 }
File name: NetworkingPeer.cs
Copy
2228 internal Hashtable SendInstantiate(string prefabName, Vector3 position, Quaternion rotation, int group, int[] viewIDs, object[] data, bool isGlobalObject)
2229 {
2230 // first viewID is now also the gameobject's instantiateId
2231 int instantiateId = viewIDs[0]; // LIMITS PHOTONVIEWS&PLAYERS
2232
2233 //TODO: reduce hashtable key usage by using a parameter array for the various values
2234 Hashtable instantiateEvent = new Hashtable(); // This players info is sent via ActorID
2235 instantiateEvent[(byte)0] = prefabName;
2236
2237 if (position != Vector3.zero)
2238 {
2239 instantiateEvent[(byte)1] = position;
2240 }
2241
2242 if (rotation != Quaternion.identity)
2243 {
2244 instantiateEvent[(byte)2] = rotation;
2245 }
2246
2247 if (group != 0)
2248 {
2249 instantiateEvent[(byte)3] = group;
2250 }
2251
2252 // send the list of viewIDs only if there are more than one. else the instantiateId is the viewID
2253 if (viewIDs.Length > 1)
2254 {
2255 instantiateEvent[(byte)4] = viewIDs; // LIMITS PHOTONVIEWS&PLAYERS
2256 }
2257
2258 if (data != null)
2259 {
2260 instantiateEvent[(byte)5] = data;
2261 }
2262
2263 if (this.currentLevelPrefix > 0)
2264 {
2265 instantiateEvent[(byte)8] = this.currentLevelPrefix; // photonview's / object's level prefix
2266 }
2267
2268 instantiateEvent[(byte)6] = this.ServerTimeInMilliSeconds;
2269 instantiateEvent[(byte)7] = instantiateId;
2270
2271
2272 RaiseEventOptions options = new RaiseEventOptions();
2273 options.CachingOption = (isGlobalObject) ? EventCaching.AddToRoomCacheGlobal : EventCaching.AddToRoomCache;
2274
2275 this.OpRaiseEvent(PunEvent.Instantiation, instantiateEvent, true, options);
2276 return instantiateEvent;
2277 }
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 }
IDS 141 lượt xem
Gõ tìm kiếm nhanh...