Problem with Network instantiation I guess?

Options
Hey all,

hopefully I don't post this in the complete wrong section.

I'm just new to Unity and Photon. Currently I try to make a small game. It is a top down shooter with a randomly generated map. This works quite fine local. Now I try to make it a multiplayer game.

The way it works is, there are "Spawn Points" which spawn room prefabs, by a random number. When there is a "Endroom" spawned it does not spawn new rooms near by.

This works fine so far and I was able to bring it to multiplayer. When I start the game, the player who creates the room is able to see all spawned rooms and everything works fine.

The Problem:
When I join with a Second Player, he can see the same rooms so far, except for 1 or 2 missing.
But it is always a different room and it is completly random in the spawn order, sometimes it is the seconed spawned room, sometimes the 20th spawned room. I can't figuer out why this is happening.

I guess there is a problem with the PhotonView or the sync between the two.

I have a Main Menu where you can click on start game, after that it will load the level, in which is the "random room" logic.

I instantiate the room prefabs as NetworkRoomObjects.

All spawnpoints and all room prefabs have a PhotonView component.

There is a error Message I don't know to get rid off, which may be the problem cause. I will attach a screenshot of it.

Any help or idea would be appreciated. I read a lot of the documentation, but I think I miss something here.

The code is probably not the best since I'm still learning. :blush:

Thank you all.

Greetings Lynocs

Bild-2021-09-17-092753.png

This is the RoomSpawner script, currently attached to a single spawnpoint in level1:
(the arrays with "B", "BL" and so on are the prefab names and stand for the opening directions, e.g. "B" > bottom opening, T = Top, R = right, L = Left. There for TL = Top and left)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using System.IO;

public class RoomSpawner : MonoBehaviourPunCallbacks
{
    public int openingDirection;
    public float waitTime = 4f;

  //  private RoomTemplates templates;
  //  private int rand;
    private bool spawned = false;

    private string[] bottomRooms = new string[] {"B", "BL", "BR", "TB"};
    private string[] topRooms = new string[] { "T", "TB", "TL", "TR" };
    private string[] leftRooms = new string[] { "L", "BL", "RL", "TBLR", "TL" };
    private string[] rightRooms = new string[] { "R", "BR", "RL", "TBLR", "TR" };
    private string[] startRooms = new string[] { "TBLR" };

    void Start() {
      Destroy(gameObject, waitTime);
        if (waitTime <= 0)
        {
            PhotonNetwork.Destroy(gameObject);
        } else
        {
            waitTime = waitTime - Time.deltaTime;
        }
    //  templates = GameObject.FindGameObjectWithTag("Rooms").GetComponent<RoomTemplates>();
        Invoke("Spawn", 0.1f);
    }

    void Spawn() {

        if (spawned == false && PhotonNetwork.IsMasterClient)
        {
            if (openingDirection == 1)
            {
                PhotonNetwork.InstantiateRoomObject(Path.Combine("Rooms", bottomRooms[Random.Range(0, bottomRooms.Length)]), transform.position, Quaternion.identity);
                spawned = true;
            }
            else if (openingDirection == 2)
            {
                PhotonNetwork.InstantiateRoomObject(Path.Combine("Rooms", topRooms[Random.Range(0, topRooms.Length)]), transform.position, Quaternion.identity);
                spawned = true;
            }
            else if (openingDirection == 3)
            {
                PhotonNetwork.InstantiateRoomObject(Path.Combine("Rooms", leftRooms[Random.Range(0, leftRooms.Length)]), transform.position, Quaternion.identity);
                spawned = true;
            }
            else if (openingDirection == 4)
            {
                PhotonNetwork.InstantiateRoomObject(Path.Combine("Rooms", rightRooms[Random.Range(0, rightRooms.Length)]), transform.position, Quaternion.identity);
                spawned = true;
            }
            else if (openingDirection == 5)
            {
                PhotonNetwork.InstantiateRoomObject(Path.Combine("Rooms", startRooms[Random.Range(0, startRooms.Length)]), transform.position, Quaternion.identity);
                spawned = true;
            }
        }
    }

    void OnTriggerEnter (Collider other){
      if (other.CompareTag("SpawnPoint")) {
        if (other.GetComponent<RoomSpawner>().spawned == false && spawned == false && PhotonNetwork.IsMasterClient)
        {
          
            PhotonNetwork.Destroy(other.gameObject);
            
            Invoke("SpawnEndings", 0.2f);
        }
        spawned = true;

        }
    }

    void SpawnEndings ()
    {
        if (PhotonNetwork.IsMasterClient)
        {
            if (openingDirection == 1)
            {
                PhotonNetwork.InstantiateRoomObject(Path.Combine("Rooms", bottomRooms[0]), transform.position, Quaternion.identity);
            }
            else if (openingDirection == 2)
            {
                PhotonNetwork.InstantiateRoomObject(Path.Combine("Rooms", topRooms[0]), transform.position, Quaternion.identity);
            }
            else if (openingDirection == 3)
            {
                PhotonNetwork.InstantiateRoomObject(Path.Combine("Rooms", leftRooms[0]), transform.position, Quaternion.identity);
            }
            else if (openingDirection == 4)
            {
                PhotonNetwork.InstantiateRoomObject(Path.Combine("Rooms", rightRooms[0]), transform.position, Quaternion.identity);
            }
        }
    }

}

This is the Lobby Script from the main menu:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;

public class QuickStartLobbyController : MonoBehaviourPunCallbacks
{
    [SerializeField]
    private GameObject quickStartButton;
    [SerializeField]
    private GameObject quickCancelButton;
    [SerializeField]
    private int roomSize;

    public override void OnConnectedToMaster()
    {
        quickStartButton.SetActive(true);
    }

    public void QuickStart()
    {
        quickStartButton.SetActive(false);
        quickCancelButton.SetActive(true);
        PhotonNetwork.JoinRandomRoom();
        Debug.Log("Quick Start");
    }

    public override void OnJoinRandomFailed(short returnCode, string message)
    {
        Debug.Log("Fehlschlag");
        CreateRoom();
    }

    void CreateRoom()
    {
        Debug.Log("Erstelle Raum");
        int randomRoomNumber = Random.Range(0, 10000);
        RoomOptions roomOps = new RoomOptions() { IsVisible = true, IsOpen = true, MaxPlayers = (byte)roomSize };
        PhotonNetwork.CreateRoom("Room" + randomRoomNumber, roomOps);
        Debug.Log(randomRoomNumber);
        
    }

    public override void OnCreateRoomFailed(short returnCode, string message)
    {
        Debug.Log("Raum erstellen fehlgeschlagen, versuche nochmal!");
        CreateRoom();
    }

    public void QuickCancel ()
    {
        quickCancelButton.SetActive(false);
        quickStartButton.SetActive(true);
        PhotonNetwork.LeaveRoom();
    }
}

This is the room controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;

public class QuickStartRoomController : MonoBehaviourPunCallbacks
{

    [SerializeField]
    public int multiplayerSceneIndex;

    public override void OnEnable()
    {
        PhotonNetwork.AddCallbackTarget(this);
    }

    public override void OnDisable()
    {
        PhotonNetwork.RemoveCallbackTarget(this);
    }

    public override void OnJoinedRoom()
    {
        Debug.Log("Raum beigetreten");
        StartGame();
        OnLevelWasLoaded(1);
    }

    private void StartGame()
    {
        PhotonNetwork.AutomaticallySyncScene = true;
        if (PhotonNetwork.IsMasterClient)
        {
            Debug.Log("Starte Spiel");
            PhotonNetwork.IsMessageQueueRunning = false;
            PhotonNetwork.LoadLevel(multiplayerSceneIndex);
            
        }
    }

    private void OnLevelWasLoaded(int level)
    {
        PhotonNetwork.IsMessageQueueRunning = true;
    }

}

And this is the game Setup Controller
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Photon.Pun;

public class GameSetupController : MonoBehaviourPunCallbacks
{
    // Start is called before the first frame update
    void Start()
    {
        PhotonNetwork.AutomaticallySyncScene = true;
        CreatePlayer();   
    }

    private void CreatePlayer()
    {
        Debug.Log("Erstelle Spieler");
        PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "Player"), Vector3.zero, Quaternion.identity);
        PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "PlayerCamera"), new Vector3(0, 15, 13), transform.rotation * Quaternion.Euler(65, 0, 0));
         
        
    }

}

Answers

  • Lynocs
    Options

    Hey Guys,

    I was able to find a solution by myself. This is probably not best practice, but I just removed the "PhotonNetwork.Destroy" from the collision detection in the RoomSpawner Script:

    void OnTriggerEnter (Collider other){
          if (other.CompareTag("SpawnPoint")) {
            if (other.GetComponent<RoomSpawner>().spawned == false && spawned == false && PhotonNetwork.IsMasterClient)
            {
              
                PhotonNetwork.Destroy(other.gameObject);
                
                Invoke("SpawnEndings", 0.2f);
            }
            spawned = true;
    
            }
        }
    

    And changed it to:

    void OnTriggerEnter (Collider other){
          if (other.CompareTag("SpawnPoint")) {
            if (other.GetComponent<RoomSpawner>().spawned == false && spawned == false && PhotonNetwork.IsMasterClient)
            {
              
                Destroy(other.gameObject);
                
                Invoke("SpawnEndings", 0.2f);
            }
            spawned = true;
    
            }
        }
    

    I have no clue why this is working, but I tested it several times and it works flawlessly.


    I post this here, in case that anybody got the same problem.


    Btw. If anybody can explain why this works, I would appreciate it. I thought when I instantiate something as RoomObject I need to destroy it with the Network Destroy?

    This Part of the Script just removes a Spawnpoint if there is already one and spawns an Endroom, just to make sure that there does not spawn several rooms into each other.

    Bye bye.

    Lynocs