PhotonViewHandler.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // ----------------------------------------------------------------------------
  2. // <copyright file="PhotonViewHandler.cs" company="Exit Games GmbH">
  3. // PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
  4. // </copyright>
  5. // <summary>
  6. // This is a Editor script to initialize PhotonView components.
  7. // </summary>
  8. // <author>developer@exitgames.com</author>
  9. // ----------------------------------------------------------------------------
  10. namespace Photon.Pun
  11. {
  12. using System.Collections.Generic;
  13. using Realtime;
  14. using UnityEditor;
  15. using UnityEngine;
  16. using Debug = UnityEngine.Debug;
  17. [InitializeOnLoad]
  18. public class PhotonViewHandler : EditorWindow
  19. {
  20. static PhotonViewHandler()
  21. {
  22. // called once per change (per key-press in inspectors) and once after play-mode ends.
  23. #if (UNITY_2018 || UNITY_2018_1_OR_NEWER)
  24. EditorApplication.hierarchyChanged += OnHierarchyChanged;
  25. #else
  26. EditorApplication.hierarchyWindowChanged += OnHierarchyChanged;
  27. #endif
  28. }
  29. internal static void OnHierarchyChanged()
  30. {
  31. // set prefabs to viewID 0 if needed
  32. // organize resource PVs in a list per viewID
  33. // process the lists: if more than one photonView is in a list, we have to resolve the clash
  34. // check if only one view had the viewId earlier
  35. // apply a new viewID to the others
  36. // update the cached list of instances and their viewID
  37. //Debug.LogWarning("OnHierarchyChanged(). isPlaying: " + Application.isPlaying);
  38. if (Application.isPlaying)
  39. {
  40. return;
  41. }
  42. PhotonView[] photonViewResources = Resources.FindObjectsOfTypeAll<PhotonView>();
  43. List<PhotonView> photonViewInstances = new List<PhotonView>();
  44. Dictionary<int, List<PhotonView>> viewInstancesPerViewId = new Dictionary<int, List<PhotonView>>();
  45. List<PhotonView> photonViewsToReassign = new List<PhotonView>();
  46. foreach (PhotonView view in photonViewResources)
  47. {
  48. if (PhotonEditorUtils.IsPrefab(view.gameObject))
  49. {
  50. // prefabs should use 0 as ViewID and sceneViewId
  51. if (view.ViewID != 0 || view.sceneViewId != 0)
  52. {
  53. view.ViewID = 0;
  54. view.sceneViewId = 0;
  55. EditorUtility.SetDirty(view);
  56. }
  57. continue; // skip prefabs in further processing
  58. }
  59. photonViewInstances.Add(view);
  60. // assign a new viewID if the viewId is lower than the minimum for this scene
  61. if (!IsViewIdOkForScene(view))
  62. {
  63. photonViewsToReassign.Add(view);
  64. continue; // this view definitely gets cleaned up, so it does not count versus duplicates, checked below
  65. }
  66. // organize the viewInstances into lists per viewID, so we know duplicate usage
  67. if (!viewInstancesPerViewId.ContainsKey(view.sceneViewId))
  68. {
  69. viewInstancesPerViewId[view.sceneViewId] = new List<PhotonView>();
  70. }
  71. viewInstancesPerViewId[view.sceneViewId].Add(view);
  72. }
  73. //Debug.Log("PreviousAssignments: "+PunSceneViews.Instance.Views.Count);
  74. foreach (List<PhotonView> list in viewInstancesPerViewId.Values)
  75. {
  76. if (list.Count <= 1)
  77. {
  78. continue; // skip lists with just one entry (the viewID is unique)
  79. }
  80. PhotonView previousAssignment = null;
  81. bool wasAssigned = PunSceneViews.Instance.Views.TryGetValue(list[0].sceneViewId, out previousAssignment);
  82. foreach (PhotonView view in list)
  83. {
  84. if (wasAssigned && view.Equals(previousAssignment))
  85. {
  86. // previously, we cached the used viewID as assigned to the current view. we don't change this.
  87. continue;
  88. }
  89. //Debug.LogWarning("View to reassign due to viewID: "+view, view.gameObject);
  90. photonViewsToReassign.Add(view);
  91. }
  92. }
  93. int i;
  94. foreach (PhotonView view in photonViewsToReassign)
  95. {
  96. i = MinSceneViewId(view);
  97. while (viewInstancesPerViewId.ContainsKey(i))
  98. {
  99. i++;
  100. }
  101. view.sceneViewId = i;
  102. viewInstancesPerViewId.Add(i, null); // we don't need the lists anymore but we care about getting the viewIDs listed
  103. EditorUtility.SetDirty(view);
  104. }
  105. // update the "semi persistent" list of viewIDs and their PhotonViews
  106. PunSceneViews.Instance.Views.Clear();
  107. foreach (PhotonView view in photonViewInstances)
  108. {
  109. if (PunSceneViews.Instance.Views.ContainsKey(view.sceneViewId))
  110. {
  111. Debug.LogError("ViewIDs should no longer have duplicates! "+view.sceneViewId, view);
  112. continue;
  113. }
  114. PunSceneViews.Instance.Views[view.sceneViewId] = view;
  115. }
  116. //Debug.Log("photonViewsToReassign.Count: "+photonViewsToReassign.Count + " count of viewIDs in use: "+viewInstancesPerViewId.Values.Count);
  117. //Debug.Log("PreviousAssignments now counts: "+PunSceneViews.Instance.Views.Count);
  118. }
  119. private static int MinSceneViewId(PhotonView view)
  120. {
  121. int result = PunSceneSettings.MinViewIdForScene(view.gameObject.scene.name);
  122. return result;
  123. }
  124. private static bool IsViewIdOkForScene(PhotonView view)
  125. {
  126. return view.sceneViewId >= MinSceneViewId(view);
  127. }
  128. }
  129. /// <summary>
  130. /// Stores a PhotonView instances per viewId (key). Instance is used as cache storage in-Editor.
  131. /// </summary>
  132. public class PunSceneViews : ScriptableObject
  133. {
  134. [SerializeField]
  135. public Dictionary<int, PhotonView> Views = new Dictionary<int, PhotonView>();
  136. private static PunSceneViews instanceField;
  137. public static PunSceneViews Instance
  138. {
  139. get
  140. {
  141. if (instanceField != null)
  142. {
  143. return instanceField;
  144. }
  145. instanceField = GameObject.FindObjectOfType<PunSceneViews>();
  146. if (instanceField == null)
  147. {
  148. instanceField = ScriptableObject.CreateInstance<PunSceneViews>();
  149. }
  150. return instanceField;
  151. }
  152. }
  153. }
  154. }