// 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;
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);
int minViewIdInThisScene = PunSceneSettings.MinViewIdForScene(Application.loadedLevelName);
//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)
{
Debug.LogWarning("PhotonView on persistent object being fixed (id and prefix must be 0). Was: " + view);
view.viewID = 0;
view.prefixBackup = -1;
EditorUtility.SetDirty(view);
fixedSomeId = true;
}
}
else
{
// keep all scene-instanced PVs for later re-check
pvInstances.Add(view);
}
}
// 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.subId != 0)
{
if (view.subId < minViewIdInThisScene || usedInstanceViewNumbers.Contains(view.subId))
{
view.subId = 0; // avoid duplicates and negative values by assigning 0 as (temporary) number to be fixed in next pass
}
else
{
usedInstanceViewNumbers.Add(view.subId); // builds a list of currently used viewIDs
}
}
}
// third pass: anything that's now 0 must get a new (not yet used) subId number
int lastUsedId = minViewIdInThisScene - 1;
foreach (PhotonView view in pvInstances)
{
if (view.subId == 0)
{
// 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));
view.subId = PhotonViewHandler.GetID(lastUsedId, usedInstanceViewNumbers);
lastUsedId = view.subId;
//// when using the Editor's serialization (view.subId in this case), this is not needed, it seems
//PrefabUtility.RecordPrefabInstancePropertyModifications(view);
EditorUtility.SetDirty(view);
fixedSomeId = true;
}
}
if (fixedSomeId)
{
//Debug.LogWarning("Some subId was adjusted."); // this log is only interesting for Exit Games
}
}