Quantcast
Channel: Photon Unity Networking (PUN) — Photon Engine
Viewing all articles
Browse latest Browse all 8947

PhotonView ID Resetting

$
0
0
Hi, I'm writing about an issue my team is trying to get around regarding PhotonView IDs being modified for prefab instances at Editor time. This is not an issue at runtime off of a build, or in Editor runtime without remote clients. However, in a multiple client situation set up using multiple Unity Editor runtime instances (i.e. not running a build runtime) running on the same or multiple systems, there is a good chance that Photon Editor script logic will modify the PhotonView ID, causing different Unity Editor instances to have different view ID sets, breaking view ID syncing. We discovered that the view ID change is being caused by PhotonViewHandler.cs modifying the PhotonView ID of the prefab itself and setting it to zero. E.g. when a prefab instance override is made, a prefab instances will get the zero value and Photon Editor logic will assign it a new ID. Reproduction steps: 1. In Editor, create a prefab and attach a PhotonView component to it. 2. In Editor, create an instance of that prefab in any scene. Observe the PhotonView ID of the instance. 3. Make a modification to the prefab in the scene hierarchy view. 4. Apply the prefab instance override change to the prefab. 5. Observe the PhotonView ID after the override. It will be different. Outside of these steps, we have also observed that a PhotonView ID changes before entering runtime (in Editor) as well. We would like to understand the official purpose/effectiveness of the ID reassignment behaviour, and how it fits with the intended usage of PhotonView IDs. In case we are misusing Photon, we are looking for advice on how to get around the issue of PhotonView ID desync across client instances. So far, the only path forward is to share a consistent build version across clients when testing multiplayer behaviour, but this isn't always efficient while developing. Thus far we have tried applying the following solutions to get around this issue (we've settled on the 3rd): 1. Use version control to sync your unity project across clients. However, this is unreliable due to IDs sometimes changing on entering Play Mode. 2. Modify the Photon Code (PhotonViewHandler.cs) to make sure the prefab ID isn't modified for a prefab and that the IsPrefab check identifies the prefab correctly. However, we wish to avoid modifying plugins at all costs, for future maintenance reasons and to avoid more undesirable issues. 3. Develop a script that maintains a list of all PhotonView gameobjects in a scene during Editor mode and uses RaiseEvents during runtime to ensure that all the PhotonView IDs are synchronized across multiple clients. (See the script attached) We are moving ahead with option 3, but it feels like overkill to do this, so we'd like to check if we're approaching this problem correctly. Thanks! Ante PhotonViewIdSync script we wrote: (partial class body simplified of irrelevant bits)

public class PhotonViewIdSync : MonoBehaviour
{
    #if UNITY_EDITOR
    
    [SerializeField] private List _photonViewInScene;
    private static List PhotonViewsInScene
    {
        get => Instance._photonViewInScene;
        set => Instance._photonViewInScene = value;
    }


    #region MonoBehaviour

    private void OnEnable()
    {
        NetworkManager.AddRaiseEventListener(RaiseEventCode.PhotonViewIDSync, ReceivePhotonViewId);
    }

    private void OnDisable()
    {
        NetworkManager.RemoveRaiseEventListener(RaiseEventCode.PhotonViewIDSync, ReceivePhotonViewId);
    }

    private void Start()
    {
        StartCoroutine(SynchronizePhotonViewID(SceneManager.GetActiveScene(), LoadSceneMode.Single));
    }

    #endregion MonoBehaviour


    #region Synchronization

    private IEnumerator SynchronizePhotonViewID(Scene scene, LoadSceneMode mode)
    {
        yield return new WaitUntil(() => NetworkManager.IsReady);
        if (!PhotonNetwork.IsMasterClient) yield break;

        Debug.LogFormat(DebugLogFormat, "SynchronizePhotonViewID", " Synchronizing Photon Views in Scene " + scene.name);
        for (int i = 0; i < PhotonViewsInScene.Count; i++)
        {
            SendPhotonViewId(i, PhotonViewsInScene[i].ViewID);
        }
    }

    public static void SendPhotonViewId(int index, int viewID)
    {
        SendOptions sendOptions = new SendOptions {Reliability = true};
        object[] eventContent = new object[] {index, viewID};
        RaiseEventOptions raiseEventOptions =
            new RaiseEventOptions {CachingOption = EventCaching.AddToRoomCache, Receivers = ReceiverGroup.Others};
        PhotonNetwork.RaiseEvent(RaiseEventCode.PhotonViewIDSync, eventContent, raiseEventOptions, sendOptions);
    }

    public void ReceivePhotonViewId(EventData photonEventData)
    {
        object[] sentData = (object[])photonEventData.CustomData;
        int index = (int)sentData[0];
        if (index < PhotonViewsInScene.Count)
        {
            PhotonViewsInScene[index].ViewID = (int)sentData[1];
        }
    }

    #endregion Synchronization


    #region EditorMode

    private static EditorBuildSettingsScene[] _scenes;
    private static int _currentSceneIndex = 0;
    private static string _activeScene;

    [MenuItem("Photon/Update Photon View List %g")]
    private static void LoadViewsToList()
    {
        if (Instance == null)
        {
            Debug.LogFormat(DebugErrorFormat, " Missing Component", " Please add a PhotonViewIDSync component to any gameobject.");
            return;
        }

        _scenes = EditorBuildSettings.scenes;

        EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
        EditorSceneManager.activeSceneChangedInEditMode += AddSceneViewsToList;
        _activeScene = EditorSceneManager.GetActiveScene().path;
        EditorSceneManager.CloseScene(EditorSceneManager.GetActiveScene(), false);
        LoadNextScene();
    }

    private static void LoadNextScene(string sceneToLoad = null)
    {
        EditorSceneManager.OpenScene(sceneToLoad ?? _scenes[_currentSceneIndex].path);
    }

    private static void AddSceneViewsToList(Scene one, Scene two)
    {
        _currentSceneIndex++;

        object[] obj = FindObjectsOfType(typeof(GameObject));
        PhotonViewsInScene = new List();
        Scene currentScene = EditorSceneManager.GetActiveScene();
        foreach (object o in obj)
        {
            GameObject newGO = (GameObject)o;
            PhotonView newView = newGO.GetComponent();
            if (newView == null) continue;

            PhotonViewsInScene.Add(newView);
            Debug.LogFormat(DebugLogFormat, "AddSceneViewsToList", "Adding PhotonView " + newGO.name);
        }

        if (_currentSceneIndex < _scenes.Length)
        {
            LoadNextScene();
        }
        else
        {
            EditorSceneManager.activeSceneChangedInEditMode -= AddSceneViewsToList;
            _currentSceneIndex = 0;
            Debug.LogFormat(DebugLogFormat, "AddSceneViewsToList", " PhotonView List Updated. ");
            EditorSceneManager.SaveScene(two);
            LoadNextScene(_activeScene);
        }
    }

    #endregion EditorMode

    #endif //UNITY_EDITOR
}

Viewing all articles
Browse latest Browse all 8947

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>