Home > Software engineering >  PhotonNetwork.Instantiate issue, player is not instantiating
PhotonNetwork.Instantiate issue, player is not instantiating

Time:07-19

I have two scripts one manages the PhotonNetwork which is responsible for loging in with nickname, creating and joining room and other instantiating the player, I have have two scenes once scene consists PhotonNetwork_Manager which has network manager scene which is shown below.

using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;

public class Photon_Manager : MonoBehaviourPunCallbacks
{
    [SerializeField] TMP_InputField nameField;
    [SerializeField] TMP_InputField roomNameField;
    [SerializeField] TMP_InputField joinRoomField;

    [SerializeField] GameObject createJoinCanvas;
    [SerializeField] GameObject logInCanvas;
    [SerializeField] GameObject createCanvas;
    [SerializeField] GameObject joinCanvas;

    [SerializeField] string sceneToLoad;

    [SerializeField] public bool createRoomStatus = false;
    [SerializeField] public bool joinRoomStatus = false;
    [SerializeField] public bool logInStatus = false;   
    public override void OnConnectedToMaster()
    {
        Debug.Log("Connected to master server");
        PhotonNetwork.JoinLobby();
    }

    public override void OnCreatedRoom()
    {
        Debug.Log("Created room: "   PhotonNetwork.CurrentRoom.Name);
    }

    void Start()
    {
        Debug.Log(" started");
    }

    public void LogIn()
    {
        StartCoroutine(waitSeconds());
        string temp = nameField.text;
        PhotonNetwork.LocalPlayer.NickName = temp;
        PhotonNetwork.ConnectUsingSettings();
        logInCanvas.SetActive(false);
        createJoinCanvas.SetActive(true);
        logInStatus = true;
        Debug.Log("LogIn Done");
    }

    public void CreateRoom()
    {
        StartCoroutine(waitSeconds());
        string roomName = roomNameField.text;
        PhotonNetwork.CreateRoom(roomName);
        createCanvas.SetActive(false);
        ChangeScene(sceneToLoad);
        createRoomStatus = true;
        Debug.Log(PhotonNetwork.LocalPlayer.NickName   " joined "   roomName);
    }

    public void JoinRoom()
    {
        StartCoroutine(waitSeconds());
        string tempRoomName = joinRoomField.text;
        PhotonNetwork.JoinRoom(tempRoomName);
        joinCanvas.SetActive(false);
        ChangeScene(sceneToLoad);
        joinRoomStatus = true;
        Debug.Log(PhotonNetwork.LocalPlayer.NickName   " joined "   tempRoomName);
    }

    public void ChangeScene(string sceneName)
    {
        StartCoroutine(waitSeconds());
        PhotonNetwork.LoadLevel(sceneName);
    }

    public IEnumerator waitSeconds()
    {
        yield return new WaitForSeconds(2.5f);
    }
}

other scene has Instantiate player to instantiate player, but whenever I run the application player is not spawned even though it has Photon view component attached to it. Below is script to instantiate player.

using UnityEngine;
using Photon.Pun;
using System.Collections;

public class Instantiate_Player : MonoBehaviour
{
    [SerializeField] GameObject playerPrefab;

    [SerializeField] float xMin;
    [SerializeField] float zMin;
    [SerializeField] float xMax;
    [SerializeField] float zMax;

    void Start()
    {
        StartCoroutine(waitSeconds());

        if (PhotonNetwork.IsConnectedAndReady)
        {
            Vector3 playerPos = new Vector3(Random.Range(xMin, xMax), 0.0f, Random.Range(zMin, zMax));
            GameObject obj = PhotonNetwork.Instantiate(playerPrefab.name, playerPos, Quaternion.identity, 1, null);
            obj.SetActive(true);
        }
    }

    public IEnumerator waitSeconds()
    {
        yield return new WaitForSeconds(1.5f);
    }

}

What could be the problem??, the player has movement script attached to it with camera as its child.

CodePudding user response:

Note that your Coroutine waitSeconds does .. absolutely nothing at all!

Using StartCoroutine does not delay the code which is calling it!

You could give it a callback to do after the time has passed like e.g.

public class Photon_Manager : MonoBehaviourPunCallbacks
{
    ...

    public void LogIn()
    {
        // You can directly pass in a lambda expression
        StartCoroutine(waitSeconds(() =>  
        {
            string temp = nameField.text;
            PhotonNetwork.LocalPlayer.NickName = temp;
            PhotonNetwork.ConnectUsingSettings();
            logInCanvas.SetActive(false);
            createJoinCanvas.SetActive(true);
            logInStatus = true;
            Debug.Log("LogIn Done");
        });
    }

    public void CreateRoom()
    {
        // or as demo pass in an explicit method
        StartCoroutine(waitSeconds(CreateRoomDelayed);
    }

    private void CreateRoomDelayed()
    {
        string roomName = roomNameField.text;
        PhotonNetwork.CreateRoom(roomName);
        createCanvas.SetActive(false);
        ChangeScene(sceneToLoad);
        createRoomStatus = true;
        Debug.Log(PhotonNetwork.LocalPlayer.NickName   " joined "   roomName);
    }

    ...

    private IEnumerator waitSeconds(Action whenDone)
    {
        yield return new WaitForSeconds(2.5f);

        whenDone?.Invoke();
    }
}

Though tbh from a user perspective it seems quite odd that I have to wait 2.5 seconds (which is looong) in order to get a reaction to e.g. clicking LogIn.


You can also make Start return IEnumerator itself. In that case Unity automatically runs it as a Coroutine:

public class Instantiate_Player : MonoBehaviour
{
    ...

    IEnumerator Start()
    {
        yield return new WaitForSeconds(1.5f);

        if (PhotonNetwork.IsConnectedAndReady)
        {
            Vector3 playerPos = new Vector3(Random.Range(xMin, xMax), 0.0f, Random.Range(zMin, zMax));
            GameObject obj = PhotonNetwork.Instantiate(playerPrefab.name, playerPos, Quaternion.identity, 1, null);
            obj.SetActive(true);
        }
    }
}

In general though:

Waiting based on a fixed time is always dirty and error prone. coul rather wait until you are actually connected:

    IEnumerator Start()
    {
        yield return new WaitUntil(() => PhotonNetwork.IsConnectedAndReady);

        Vector3 playerPos = new Vector3(Random.Range(xMin, xMax), 0.0f, Random.Range(zMin, zMax));
        GameObject obj = PhotonNetwork.Instantiate(playerPrefab.name, playerPos, Quaternion.identity, 1, null);
        obj.SetActive(true);
    }
  • Related