Exemplo n.º 1
0
    public override void OnInspectorGUI()
    {
        this.m_Target = (PhotonView)target;
        bool isProjectPrefab = PhotonEditorUtils.IsPrefab(this.m_Target.gameObject);

        if (this.m_Target.ObservedComponents == null)
        {
            this.m_Target.ObservedComponents = new System.Collections.Generic.List <Component>();
        }

        if (this.m_Target.ObservedComponents.Count == 0)
        {
            this.m_Target.ObservedComponents.Add(null);
        }

        EditorGUILayout.BeginHorizontal();
        // Owner
        if (isProjectPrefab)
        {
            EditorGUILayout.LabelField("Owner:", "Set at runtime");
        }
        else if (!this.m_Target.isOwnerActive)
        {
            EditorGUILayout.LabelField("Owner", "Scene");
        }
        else
        {
            PhotonPlayer owner     = this.m_Target.owner;
            string       ownerInfo = (owner != null) ? owner.NickName : "<no PhotonPlayer found>";

            if (string.IsNullOrEmpty(ownerInfo))
            {
                ownerInfo = "<no playername set>";
            }

            EditorGUILayout.LabelField("Owner", "[" + this.m_Target.ownerId + "] " + ownerInfo);
        }

        // ownership requests
        EditorGUI.BeginDisabledGroup(Application.isPlaying);
        OwnershipOption own = (OwnershipOption)EditorGUILayout.EnumPopup(this.m_Target.ownershipTransfer, GUILayout.Width(100));

        if (own != this.m_Target.ownershipTransfer)
        {
            // jf: fixed 5 and up prefab not accepting changes if you quit Unity straight after change.
            // not touching the define nor the rest of the code to avoid bringing more problem than solving.
            EditorUtility.SetDirty(this.m_Target);

            Undo.RecordObject(this.m_Target, "Change PhotonView Ownership Transfer");
            this.m_Target.ownershipTransfer = own;
        }
        EditorGUI.EndDisabledGroup();

        EditorGUILayout.EndHorizontal();


        // View ID
        if (isProjectPrefab)
        {
            EditorGUILayout.LabelField("View ID", "Set at runtime");
        }
        else if (EditorApplication.isPlaying)
        {
            EditorGUILayout.LabelField("View ID", this.m_Target.viewID.ToString());
        }
        else
        {
            int idValue = EditorGUILayout.IntField("View ID [1.." + (PhotonNetwork.MAX_VIEW_IDS - 1) + "]", this.m_Target.viewID);
            if (this.m_Target.viewID != idValue)
            {
                Undo.RecordObject(this.m_Target, "Change PhotonView viewID");
                this.m_Target.viewID = idValue;
            }
        }

        // Locally Controlled
        if (EditorApplication.isPlaying)
        {
            string masterClientHint = PhotonNetwork.isMasterClient ? "(master)" : "";
            EditorGUILayout.Toggle("Controlled locally: " + masterClientHint, this.m_Target.isMine);
        }

        // ViewSynchronization (reliability)
        if (this.m_Target.synchronization == ViewSynchronization.Off)
        {
            GUI.color = Color.grey;
        }

        EditorGUILayout.PropertyField(serializedObject.FindProperty("synchronization"), new GUIContent("Observe option:"));

        if (this.m_Target.synchronization != ViewSynchronization.Off && this.m_Target.ObservedComponents.FindAll(item => item != null).Count == 0)
        {
            GUILayout.BeginVertical(GUI.skin.box);
            GUILayout.Label("Warning", EditorStyles.boldLabel);
            GUILayout.Label("Setting the synchronization option only makes sense if you observe something.");
            GUILayout.EndVertical();
        }

        DrawSpecificTypeSerializationOptions();

        GUI.color = Color.white;
        DrawObservedComponentsList();

        // Cleanup: save and fix look
        if (GUI.changed)
        {
            #if !UNITY_MIN_5_3
            EditorUtility.SetDirty(this.m_Target);
            #endif
            PhotonViewHandler.HierarchyChange(); // TODO: check if needed
        }

        GUI.color = Color.white;
        #if !UNITY_MIN_5_3
        EditorGUIUtility.LookLikeControls();
        #endif
    }
Exemplo n.º 2
0
 public static bool IsInTheSceneInPlayMode(GameObject go)
 {
     return(Application.isPlaying && !PhotonEditorUtils.IsPrefab(go));
 }
        public override void OnInspectorGUI()
        {
            this.serializedObject.UpdateIfRequiredOrScript();

            VoiceLogger.ExposeLogLevel(this.serializedObject, this.connection);
            EditorGUI.BeginChangeCheck();
            this.connection.GlobalRecordersLogLevel = VoiceLogger.ExposeLogLevel(this.globalRecordersLogLevelSp);
            this.connection.GlobalSpeakersLogLevel  = VoiceLogger.ExposeLogLevel(this.globalSpeakersLogLevelSp);
            EditorGUILayout.PropertyField(this.autoCreateSpeakerIfNotFoundSp, new GUIContent("Create Speaker If Not Found", "Auto instantiate a GameObject and attach a Speaker component to link to a remote audio stream if no candidate could be foun"));
            EditorGUILayout.PropertyField(this.updateIntervalSp, new GUIContent("Update Interval (ms)", "time [ms] between consecutive SendOutgoingCommands calls"));
            if (PhotonVoiceEditorUtils.IsInTheSceneInPlayMode(this.connection.gameObject))
            {
                this.connection.PrimaryRecorder = EditorGUILayout.ObjectField(
                    new GUIContent("Primary Recorder", "Main Recorder to be used for transmission by default"),
                    this.connection.PrimaryRecorder, typeof(Recorder), true) as Recorder;
                if (this.connection.SpeakerPrefab == null)
                {
                    EditorGUILayout.HelpBox("Speaker prefab needs to have a Speaker component in the hierarchy.", MessageType.Info);
                }
                this.connection.SpeakerPrefab = EditorGUILayout.ObjectField(new GUIContent("Speaker Prefab",
                                                                                           "Prefab that contains Speaker component to be instantiated when receiving a new remote audio source info"), this.connection.SpeakerPrefab,
                                                                            typeof(GameObject), false) as GameObject;
                EditorGUILayout.PropertyField(this.globalPlayDelaySettingsSp, new GUIContent("Global Playback Delay Configuration", "Remote audio stream playback delay to compensate packets latency variations."), true);
                this.connection.SetGlobalPlaybackDelaySettings(
                    this.globalPlayDelaySettingsSp.FindPropertyRelative("MinDelaySoft").intValue,
                    this.globalPlayDelaySettingsSp.FindPropertyRelative("MaxDelaySoft").intValue,
                    this.globalPlayDelaySettingsSp.FindPropertyRelative("MaxDelayHard").intValue);
            }
            else
            {
                EditorGUILayout.PropertyField(this.enableSupportLoggerSp, new GUIContent("Support Logger", "Logs additional info for debugging.\nUse this when you submit bugs to the Photon Team."));
                #if !UNITY_ANDROID && !UNITY_IOS
                EditorGUILayout.PropertyField(this.runInBackground, new GUIContent("Run In Background", "Sets Unity's Application.runInBackground: Should the application keep running when the application is in the background?"));
                #endif
                #if !UNITY_IOS
                EditorGUILayout.PropertyField(this.keepAliveInBackgroundSp, new GUIContent("Background Timeout (ms)", "Defines for how long the Fallback Thread should keep the connection, before it may time out as usual."));
                #endif
                EditorGUILayout.PropertyField(this.applyDontDestroyOnLoadSp, new GUIContent("Don't Destroy On Load", "Persists the GameObject across scenes using Unity's GameObject.DontDestroyOnLoad"));
                if (this.applyDontDestroyOnLoadSp.boolValue && !PhotonEditorUtils.IsPrefab(this.connection.gameObject))
                {
                    if (this.connection.transform.parent != null)
                    {
                        EditorGUILayout.HelpBox("DontDestroyOnLoad only works for root GameObjects or components on root GameObjects.", MessageType.Warning);
                        if (GUILayout.Button("Detach"))
                        {
                            this.connection.transform.parent = null;
                        }
                    }
                }
                EditorGUILayout.PropertyField(this.primaryRecorderSp,
                                              new GUIContent("Primary Recorder", "Main Recorder to be used for transmission by default"));
                GameObject prefab = this.speakerPrefabSp.objectReferenceValue as GameObject;
                if (prefab == null)
                {
                    EditorGUILayout.HelpBox("Speaker prefab needs to have a Speaker component in the hierarchy.", MessageType.Info);
                }
                prefab = EditorGUILayout.ObjectField(new GUIContent("Speaker Prefab",
                                                                    "Prefab that contains Speaker component to be instantiated when receiving a new remote audio source info"), prefab,
                                                     typeof(GameObject), false) as GameObject;
                if (prefab == null || prefab.GetComponentInChildren <Speaker>() != null)
                {
                    this.speakerPrefabSp.objectReferenceValue = prefab;
                }
                else
                {
                    Debug.LogError("SpeakerPrefab must have a component of type Speaker in its hierarchy.", this);
                }
                EditorGUILayout.PropertyField(this.globalPlayDelaySettingsSp, new GUIContent("Global Playback Delay Settings", "Remote audio stream playback delay to compensate packets latency variations."), true);
            }
            if (!this.connection.Client.IsConnected)
            {
                this.DisplayAppSettings();
            }
            EditorGUILayout.PropertyField(this.statsResetInterval, new GUIContent("Stats Reset Interval (ms)", "time [ms] between statistics calculations"));

            if (EditorGUI.EndChangeCheck())
            {
                this.serializedObject.ApplyModifiedProperties();
            }

            if (PhotonVoiceEditorUtils.IsInTheSceneInPlayMode(this.connection.gameObject))
            {
                this.DisplayVoiceStats();
                this.DisplayDebugInfo(this.connection.Client);
                this.DisplayCachedVoiceInfo();
                this.DisplayTrafficStats(this.connection.Client.LoadBalancingPeer);
            }
        }
Exemplo n.º 4
0
    // 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 (PhotonEditorUtils.IsPrefab(view.gameObject))
            {
                if (view.viewID != 0 || view.prefixBackup != -1 || view.instantiationId != -1)
                {
                                        #if !UNITY_2018_3_OR_NEWER
                    Debug.LogWarning("PhotonView on persistent object being fixed (id and prefix must be 0). Was: " + view);
                                        #endif
                    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
        }
    }