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.
Thank you all.
Greetings Lynocs
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)
This is the Lobby Script from the main menu:
This is the room controller:
And this is the game Setup Controller
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.
Thank you all.
Greetings Lynocs
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)); } }
0
Answers
-
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
0