Character Selector - Photon, Unity

Hi,

I am having trouble with getting my character to launch in a room. We were able to get it working on PC but when launching via Pico headset, the character stays in the lobby and wont join in the room. I can hear the other users but its not connecting. If you have some ideas on how i can make this work better, I would appreciate it.

Within Unity, we modified the following:

using savedPlayer = ExitGames.Client.Photon.Hashtable;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.Serialization;


using Photon.Realtime;

using UnityEngine.Events;


#if UNITY_EDITOR

using UnityEditor;

#endif


namespace Photon.Pun.UtilityScripts

{


  /// <summary>

  /// This component will instantiate a network GameObject when a room is joined

  /// </summary>

  public class OnJoinedInstantiateEdited : MonoBehaviour

    , IMatchmakingCallbacks

  {

    public ModelList modelList;

    public Player player {get; private set;}


     

    public enum SpawnSequence { Connection, Random, RoundRobin, Transform }


    #region Inspector Items


    // Old field, only here for backwards compat. Value copies over to SpawnPoints in OnValidate

    [HideInInspector] private Transform SpawnPosition;


    [HideInInspector] public SpawnSequence Sequence = SpawnSequence.Transform;


    [HideInInspector] public List<Transform> SpawnPoints = new List<Transform>(1) { null };


    [Tooltip("Add a random variance to a spawn point position. GetRandomOffset() can be overridden with your own method for producing offsets.")]

    [HideInInspector] public bool UseRandomOffset = true;


    [Tooltip("Radius of the RandomOffset.")]

    [FormerlySerializedAs("PositionOffset")]

    [HideInInspector] public float RandomOffset = 2.0f;


    [Tooltip("Disables the Y axis of RandomOffset. The Y value of the spawn point will be used.")]

    [HideInInspector] public bool ClampY = true;


    [HideInInspector] public List<GameObject> PrefabsToInstantiate = new List<GameObject>(1) { null }; // set in inspector


    [FormerlySerializedAs("autoSpawnObjects")]

    [HideInInspector] public bool AutoSpawnObjects = true;


    #endregion


    // Record of spawned objects, used for Despawn All

    public Stack<GameObject> SpawnedObjects = new Stack<GameObject>();

    protected int spawnedAsActorId;




#if UNITY_EDITOR


    protected void OnValidate()

    {

      /// Check the prefab to make sure it is the actual resource, and not a scene object or other instance.

      if (PrefabsToInstantiate != null)

        for (int i = 0; i < PrefabsToInstantiate.Count; ++i)

        {

          var prefab = PrefabsToInstantiate[i];

          if (prefab)

            PrefabsToInstantiate[i] = ValidatePrefab(prefab);

        }


      /// Move any values from old SpawnPosition field to new SpawnPoints

      if (SpawnPosition)

      {

        if (SpawnPoints == null)

          SpawnPoints = new List<Transform>();


        SpawnPoints.Add(SpawnPosition);

        SpawnPosition = null;

      }

    }


    /// <summary>

    /// Validate, and if valid add this prefab to the first null element of the list, or create a new element. Returns true if the object was added.

    /// </summary>

    /// <param name="prefab"></param>

    public bool AddPrefabToList(GameObject prefab)

    {

      var validated = ValidatePrefab(prefab);

      if (validated)

      {

        // Don't add to list if this prefab already is on the list

        if (PrefabsToInstantiate.Contains(validated))

          return false;


        // First try to use any null array slots to keep things tidy

        if (PrefabsToInstantiate.Contains(null))

          PrefabsToInstantiate[PrefabsToInstantiate.IndexOf(null)] = validated;

        // Otherwise, just add this prefab.

        else

          PrefabsToInstantiate.Add(validated);

        return true;

      }


      return false;


    }



    private void Start()

    {

      GameObject playerToSpawn = modelList.listOfModels[(int)PhotonNetwork.LocalPlayer.CustomProperties["characterNo"]];

      AddPrefabToList(playerToSpawn);

       

    }


    /// <summary>

    /// Determines if the supplied GameObject is an instance of a prefab, or the actual source Asset, 

    /// and returns a best guess at the actual resource the dev intended to use.

    /// </summary>

    /// <returns></returns>

    protected static GameObject ValidatePrefab(GameObject unvalidated)

    {

      if (unvalidated == null)

        return null;


      if (!unvalidated.GetComponent<PhotonView>())

        return null;


#if UNITY_2018_3_OR_NEWER


GameObject validated = null;


if (unvalidated != null)

{


if (PrefabUtility.IsPartOfPrefabAsset(unvalidated))

return unvalidated;


var prefabStatus = PrefabUtility.GetPrefabInstanceStatus(unvalidated);

var isValidPrefab = prefabStatus == PrefabInstanceStatus.Connected || prefabStatus == PrefabInstanceStatus.Disconnected;


if (isValidPrefab)

validated = PrefabUtility.GetCorrespondingObjectFromSource(unvalidated) as GameObject;

else

return null;


if (!PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(validated).Contains("/Resources"))

Debug.LogWarning("Player Prefab needs to be a Prefab in a Resource folder.");

}

#else

      GameObject validated = unvalidated;


      if (unvalidated != null && PrefabUtility.GetPrefabType(unvalidated) != PrefabType.Prefab)

        validated = PrefabUtility.GetPrefabParent(unvalidated) as GameObject;

#endif

      return validated;

    }


#endif



    public virtual void OnEnable()

    {

      PhotonNetwork.AddCallbackTarget(this);

    }


    public virtual void OnDisable()

    {

      PhotonNetwork.RemoveCallbackTarget(this);

    }



    public UnityEvent OnJoinedPhoton, OnJoinedAsHost;

    public virtual void OnJoinedRoom()

    {

      // Only AutoSpawn if we are a new ActorId. Rejoining should reproduce the objects by server instantiation.

      if (AutoSpawnObjects && !PhotonNetwork.LocalPlayer.HasRejoined)

      {

        SpawnObjects();

        OnJoinedPhoton.Invoke();


        if (PhotonNetwork.IsMasterClient)

        {

          OnJoinedAsHost.Invoke();

        }

      }

    }


    public virtual void SpawnObjects()

    {

      if (this.PrefabsToInstantiate != null)

      {

        foreach (GameObject o in this.PrefabsToInstantiate)

        {

          if (o == null)

            continue;

#if UNITY_EDITOR

          Debug.Log("Auto-Instantiating: " + o.name);

#endif

          Vector3 spawnPos; Quaternion spawnRot;

          GetSpawnPoint(out spawnPos, out spawnRot);



          var newobj = PhotonNetwork.Instantiate(o.name, spawnPos, spawnRot, 0);

          SpawnedObjects.Push(newobj);

        }

      }

    }


    /// <summary>

    /// Destroy all objects that have been spawned by this component for this client.

    /// </summary>

    /// <param name="localOnly">Use Object.Destroy rather than PhotonNetwork.Destroy.</param>

    public virtual void DespawnObjects(bool localOnly)

    {


      while (SpawnedObjects.Count > 0)

      {

        var go = SpawnedObjects.Pop();

        if (go)

        {

          if (localOnly)

            Object.Destroy(go);

          else

            PhotonNetwork.Destroy(go);


        }

      }

    }


    public virtual void OnFriendListUpdate(List<FriendInfo> friendList) { }

    public virtual void OnCreatedRoom() { }

    public virtual void OnCreateRoomFailed(short returnCode, string message) { }

    public virtual void OnJoinRoomFailed(short returnCode, string message) { }

    public virtual void OnJoinRandomFailed(short returnCode, string message) { }

    public virtual void OnLeftRoom() { }


    protected int lastUsedSpawnPointIndex = -1;


    /// <summary>

    /// Gets the next SpawnPoint from the list using the SpawnSequence, and applies RandomOffset (if used) to the transform matrix.

    /// Override this method with any custom code for coming up with a spawn location. This method is used by AutoSpawn.

    /// </summary>

    public virtual void GetSpawnPoint(out Vector3 spawnPos, out Quaternion spawnRot)

    {


      // Fetch a point using the Sequence method indicated

      Transform point = GetSpawnPoint();


      if (point != null)

      {

        spawnPos = point.position;

        spawnRot = point.rotation;

      }

      else

      {

        spawnPos = new Vector3(0, 0, 0);

        spawnRot = new Quaternion(0, 0, 0, 1);

      }

       

      if (UseRandomOffset)

      {

        Random.InitState((int)(Time.time * 10000));

        spawnPos += GetRandomOffset();

      }

    }

     


    /// <summary>

    /// Get the transform of the next SpawnPoint from the list, selected using the SpawnSequence setting. 

    /// RandomOffset is not applied, only the transform of the SpawnPoint is returned.

    /// Override this method to change how Spawn Point transform is selected. Return the transform you want to use as a spawn point.

    /// </summary>

    /// <returns></returns>

    protected virtual Transform GetSpawnPoint()

    {

      // Fetch a point using the Sequence method indicated

      if (SpawnPoints == null || SpawnPoints.Count == 0)

      {

        return null;

      }

      else

      {

        switch (Sequence)

        {

          case SpawnSequence.Connection:

            {

              int id = PhotonNetwork.LocalPlayer.ActorNumber;

              return SpawnPoints[(id == -1) ? 0 : id % SpawnPoints.Count];

            }


          case SpawnSequence.RoundRobin:

            {

              lastUsedSpawnPointIndex++;

              if (lastUsedSpawnPointIndex >= SpawnPoints.Count)

                lastUsedSpawnPointIndex = 0;


              /// Use Vector.Zero and Quaternion.Identity if we are dealing with no or a null spawnpoint.

              return SpawnPoints == null || SpawnPoints.Count == 0 ? null : SpawnPoints[lastUsedSpawnPointIndex];

            }


          case SpawnSequence.Random:

            {

              return SpawnPoints[Random.Range(0, SpawnPoints.Count)];

            }


          case SpawnSequence.Transform:

            {

              return transform;

            }


          default:

            return null;

        }

      }

    }


    /// <summary>

    /// When UseRandomeOffset is enabled, this method is called to produce a Vector3 offset. The default implementation clamps the Y value to zero. You may override this with your own implementation.

    /// </summary>

    protected virtual Vector3 GetRandomOffset()

    {

      Vector3 random = Random.insideUnitSphere;

      if (ClampY)

        random.y = 0;

      return RandomOffset * random.normalized;

    }


  }


#if UNITY_EDITOR


  [CustomEditor(typeof(OnJoinedInstantiateEdited), true)]

  [CanEditMultipleObjects]

  public class OnJoinedInstantiateEditorEdited : Editor

  {


    SerializedProperty SpawnPoints, PrefabsToInstantiate, UseRandomOffset, ClampY, RandomOffset, Sequence, autoSpawnObjects;

    GUIStyle fieldBox;


    private void OnEnable()

    {

      SpawnPoints = serializedObject.FindProperty("SpawnPoints");

      PrefabsToInstantiate = serializedObject.FindProperty("PrefabsToInstantiate");

      UseRandomOffset = serializedObject.FindProperty("UseRandomOffset");

      ClampY = serializedObject.FindProperty("ClampY");

      RandomOffset = serializedObject.FindProperty("RandomOffset");

      Sequence = serializedObject.FindProperty("Sequence");


      autoSpawnObjects = serializedObject.FindProperty("AutoSpawnObjects");

    }


    public override void OnInspectorGUI()

    {

      base.OnInspectorGUI();


      const int PAD = 6;


      if (fieldBox == null)

        fieldBox = new GUIStyle("HelpBox") { padding = new RectOffset(PAD, PAD, PAD, PAD) };


      EditorGUI.BeginChangeCheck();


      EditableReferenceList(PrefabsToInstantiate, new GUIContent(PrefabsToInstantiate.displayName, PrefabsToInstantiate.tooltip), fieldBox);


      EditableReferenceList(SpawnPoints, new GUIContent(SpawnPoints.displayName, SpawnPoints.tooltip), fieldBox);


      /// Spawn Pattern

      EditorGUILayout.BeginVertical(fieldBox);

      EditorGUILayout.PropertyField(Sequence);

      EditorGUILayout.PropertyField(UseRandomOffset);

      if (UseRandomOffset.boolValue)

      {

        EditorGUILayout.PropertyField(RandomOffset);

        EditorGUILayout.PropertyField(ClampY);

      }

      EditorGUILayout.EndVertical();


      /// Auto/Manual Spawn

      EditorGUILayout.BeginVertical(fieldBox);

      EditorGUILayout.PropertyField(autoSpawnObjects);

      EditorGUILayout.EndVertical();


      if (EditorGUI.EndChangeCheck())

      {

        serializedObject.ApplyModifiedProperties();

      }

    }


    /// <summary>

    /// Create a basic rendered list of objects from a SerializedProperty list or array, with Add/Destroy buttons.

    /// </summary>

    /// <param name="list"></param>

    /// <param name="gc"></param>

    public void EditableReferenceList(SerializedProperty list, GUIContent gc, GUIStyle style = null)

    {

      EditorGUILayout.LabelField(gc);


      if (style == null)

        style = new GUIStyle("HelpBox") { padding = new RectOffset(6, 6, 6, 6) };


      EditorGUILayout.BeginVertical(style);


      int count = list.arraySize;


      if (count == 0)

      {

        if (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.MaxWidth(20)), "+", (GUIStyle)"minibutton"))

        {

          int newindex = list.arraySize;

          list.InsertArrayElementAtIndex(0);

          list.GetArrayElementAtIndex(0).objectReferenceValue = null;

        }

      }

      else

      {

        // List Elements and Delete buttons

        for (int i = 0; i < count; ++i)

        {

          EditorGUILayout.BeginHorizontal();

          bool add = (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.MaxWidth(20)), "+", (GUIStyle)"minibutton"));

          EditorGUILayout.PropertyField(list.GetArrayElementAtIndex(i), GUIContent.none);

          bool remove = (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.MaxWidth(20)), "x", (GUIStyle)"minibutton"));


          EditorGUILayout.EndHorizontal();


          if (add)

          {

            Add(list, i);

            break;

          }


          if (remove)

          {

            list.DeleteArrayElementAtIndex(i);

            //EditorGUILayout.EndHorizontal();

            break;

          }

        }


        EditorGUILayout.GetControlRect(false, 4);

         

        if (GUI.Button(EditorGUILayout.GetControlRect(), "Add", (GUIStyle)"minibutton"))

          Add(list, count);


      }

        


      EditorGUILayout.EndVertical();

    }


    private void Add(SerializedProperty list, int i)

    {

      {

        int newindex = list.arraySize;

        list.InsertArrayElementAtIndex(i);

        list.GetArrayElementAtIndex(i).objectReferenceValue = null;

      }

    }

  }

  


#endif

}