mirror of
https://github.com/FriendshipIsEpic/FiE-Game.git
synced 2024-11-25 15:08:00 +01:00
194 lines
7.3 KiB
C#
194 lines
7.3 KiB
C#
#if UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2
|
|
#define UNITY_MIN_5_3
|
|
#endif
|
|
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using System.Collections;
|
|
using Debug = UnityEngine.Debug;
|
|
using UnityEditor.SceneManagement;
|
|
|
|
[InitializeOnLoad]
|
|
public class PhotonViewHandler : EditorWindow
|
|
{
|
|
private static bool CheckSceneForStuckHandlers = true;
|
|
|
|
static PhotonViewHandler()
|
|
{
|
|
// hierarchyWindowChanged is called on hierarchy changed and on save. It's even called when hierarchy-window is closed and if a prefab with instances is changed.
|
|
// this is not called when you edit a instance's value but: on save
|
|
EditorApplication.hierarchyWindowChanged += HierarchyChange;
|
|
}
|
|
|
|
// this method corrects the IDs for photonviews in the scene and in prefabs
|
|
// make sure prefabs always use viewID 0
|
|
// make sure instances never use a owner
|
|
// this is a editor class that should only run if not playing
|
|
internal static void HierarchyChange()
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
//Debug.Log("HierarchyChange ignored, while running.");
|
|
CheckSceneForStuckHandlers = true; // done once AFTER play mode.
|
|
return;
|
|
}
|
|
|
|
if (CheckSceneForStuckHandlers)
|
|
{
|
|
CheckSceneForStuckHandlers = false;
|
|
PhotonNetwork.InternalCleanPhotonMonoFromSceneIfStuck();
|
|
}
|
|
|
|
HashSet<PhotonView> pvInstances = new HashSet<PhotonView>();
|
|
HashSet<int> usedInstanceViewNumbers = new HashSet<int>();
|
|
bool fixedSomeId = false;
|
|
|
|
//// the following code would be an option if we only checked scene objects (but we can check all PVs)
|
|
//PhotonView[] pvObjects = GameObject.FindSceneObjectsOfType(typeof(PhotonView)) as PhotonView[];
|
|
//Debug.Log("HierarchyChange. PV Count: " + pvObjects.Length);
|
|
|
|
string levelName = SceneManagerHelper.ActiveSceneName;
|
|
#if UNITY_EDITOR
|
|
levelName = SceneManagerHelper.EditorActiveSceneName;
|
|
#endif
|
|
int minViewIdInThisScene = PunSceneSettings.MinViewIdForScene(levelName);
|
|
//Debug.Log("Level '" + Application.loadedLevelName + "' has a minimum ViewId of: " + minViewIdInThisScene);
|
|
|
|
PhotonView[] pvObjects = Resources.FindObjectsOfTypeAll(typeof(PhotonView)) as PhotonView[];
|
|
|
|
foreach (PhotonView view in pvObjects)
|
|
{
|
|
// first pass: fix prefabs to viewID 0 if they got a view number assigned (cause they should not have one!)
|
|
if (EditorUtility.IsPersistent(view.gameObject))
|
|
{
|
|
if (view.viewID != 0 || view.prefixBackup != -1 || view.instantiationId != -1)
|
|
{
|
|
Debug.LogWarning("PhotonView on persistent object being fixed (id and prefix must be 0). Was: " + view);
|
|
view.viewID = 0;
|
|
view.prefixBackup = -1;
|
|
view.instantiationId = -1;
|
|
EditorUtility.SetDirty(view); // even in Unity 5.3+ it's OK to SetDirty() for non-scene objects.
|
|
fixedSomeId = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// keep all scene-instanced PVs for later re-check
|
|
pvInstances.Add(view);
|
|
}
|
|
}
|
|
|
|
Dictionary<GameObject, int> idPerObject = new Dictionary<GameObject, int>();
|
|
|
|
// second pass: check all used-in-scene viewIDs for duplicate viewIDs (only checking anything non-prefab)
|
|
// scene-PVs must have user == 0 (scene/room) and a subId != 0
|
|
foreach (PhotonView view in pvInstances)
|
|
{
|
|
if (view.ownerId > 0)
|
|
{
|
|
Debug.Log("Re-Setting Owner ID of: " + view);
|
|
}
|
|
view.ownerId = 0; // simply make sure no owner is set (cause room always uses 0)
|
|
view.prefix = -1; // TODO: prefix could be settable via inspector per scene?!
|
|
|
|
if (view.viewID != 0)
|
|
{
|
|
if (view.viewID < minViewIdInThisScene || usedInstanceViewNumbers.Contains(view.viewID))
|
|
{
|
|
view.viewID = 0; // avoid duplicates and negative values by assigning 0 as (temporary) number to be fixed in next pass
|
|
}
|
|
else
|
|
{
|
|
usedInstanceViewNumbers.Add(view.viewID); // builds a list of currently used viewIDs
|
|
|
|
int instId = 0;
|
|
if (idPerObject.TryGetValue(view.gameObject, out instId))
|
|
{
|
|
view.instantiationId = instId;
|
|
}
|
|
else
|
|
{
|
|
view.instantiationId = view.viewID;
|
|
idPerObject[view.gameObject] = view.instantiationId;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// third pass: anything that's now 0 must get a new (not yet used) ID (starting at 0)
|
|
int lastUsedId = (minViewIdInThisScene > 0) ? minViewIdInThisScene - 1 : 0;
|
|
|
|
foreach (PhotonView view in pvInstances)
|
|
{
|
|
if (view.viewID == 0)
|
|
{
|
|
Undo.RecordObject(view, "Automatic viewID change for: "+view.gameObject.name);
|
|
|
|
// 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));
|
|
int nextViewId = PhotonViewHandler.GetID(lastUsedId, usedInstanceViewNumbers);
|
|
|
|
view.viewID = nextViewId;
|
|
|
|
int instId = 0;
|
|
if (idPerObject.TryGetValue(view.gameObject, out instId))
|
|
{
|
|
view.instantiationId = instId;
|
|
}
|
|
else
|
|
{
|
|
view.instantiationId = view.viewID;
|
|
idPerObject[view.gameObject] = nextViewId;
|
|
}
|
|
|
|
lastUsedId = nextViewId;
|
|
fixedSomeId = true;
|
|
|
|
#if !UNITY_MIN_5_3
|
|
EditorUtility.SetDirty(view);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
if (fixedSomeId)
|
|
{
|
|
//Debug.LogWarning("Some subId was adjusted."); // this log is only interesting for Exit Games
|
|
}
|
|
}
|
|
|
|
// TODO fail if no ID was available anymore
|
|
// TODO look up lower numbers if offset hits max?!
|
|
public static int GetID(int idOffset, HashSet<int> usedInstanceViewNumbers)
|
|
{
|
|
while (idOffset < PhotonNetwork.MAX_VIEW_IDS)
|
|
{
|
|
idOffset++;
|
|
if (!usedInstanceViewNumbers.Contains(idOffset))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return idOffset;
|
|
}
|
|
|
|
//TODO: check if this can be internal protected (as source in editor AND as dll)
|
|
public static void LoadAllScenesToFix()
|
|
{
|
|
string[] scenes = System.IO.Directory.GetFiles(".", "*.unity", SearchOption.AllDirectories);
|
|
|
|
foreach (string scene in scenes)
|
|
{
|
|
EditorSceneManager.OpenScene(scene);
|
|
PhotonViewHandler.HierarchyChange();//NOTE: most likely on load also triggers a hierarchy change
|
|
EditorSceneManager.SaveOpenScenes();
|
|
}
|
|
|
|
Debug.Log("Corrected scene views where needed.");
|
|
}
|
|
}
|
|
|