unity-game-enginenetwork-programmingphoton

How to assert a spawn is "filled"?


I have two spawn spots where a player will show up upon connection.

I need that, when one of the players connects on one of the spots, any other player will always spawn at the other spot.


Solution

  • You can add those two possible spawn spots as empty game objects. Then I'd make a boolean array and set its states to true or false depending on if the spot is occupied. The spots aren't directly stored in this array so you should make another array. In C# this would approximately look like this:

        public GameObject[] Spots = new GameObject[2]; //Drag the spots in here (In the editor)
    bool[] OccupiedSpawnSpots = new bool[2];
    int mySpotNumber = -1;
    
    void Start() {
        PhotonNetwork.ConnectUsingSettings ("v1.0.0");
    }
    
    void OnGUI() {
        GUILayout.Label (PhotonNetwork.connectionStateDetailed.ToString ());
    }
    
    void OnJoinedLobby() 
    {
        Debug.Log ("Joined the lobby");
        PhotonNetwork.JoinRandomRoom ();
    }
    
    void OnPhotonRandomJoinFailed() 
    {
        Debug.Log ("No room found. Creating a new one...");
        PhotonNetwork.CreateRoom (null);
    }
    
    void OnPhotonPlayerConnected(PhotonPlayer player)
    {
        //If we are the MasterClient, send the list to the connected player
        if (PhotonNetwork.isMasterClient)
            GetComponent<PhotonView>().RPC("RPC_SendList", player, OccupiedSpawnSpots);
    }
    
    void OnApplicationQuit()
    {
        //If I am outside and others want to connect, my spot shouldn't be still set as occupied:
        //I mean if the application quits I'm of course going to be disconnected. 
        //You have to do this in every possibility of getting disconnected or leaving the room
        OccupiedSpawnSpots[mySpotNumber] = false;
        //Send the changed List to the others
        GetComponent<PhotonView>().RPC("RPC_UpdateList", PhotonTargets.All, OccupiedSpawnSpots);
    }
    
    [RPC]
    void RPC_SendList(bool[] ListOfMasterClient)
    {
        OccupiedSpawnSpots = ListOfMasterClient;
    
        //Get the free one
        if (OccupiedSpawnSpots[0] == false)
        {
            //Spawn your player at 0
            SpawnMyPlayer(0);
            //Set it to occupied
            OccupiedSpawnSpots[0] = true;
        } 
        else //so the other must be free
        {
            //Spawn your player at 1
            SpawnMyPlayer(1);
            //Set it to occupied
            OccupiedSpawnSpots[1] = true;
        }
    
        //Send the changed List to the others
        GetComponent<PhotonView>().RPC("RPC_UpdateList", PhotonTargets.All, OccupiedSpawnSpots);
    }
    
    [RPC]
    void RPC_UpdateList(bool[] RecentList)
    {
        OccupiedSpawnSpots = RecentList;
    }
    
    void SpawnMyPlayer(int SpotNumber) {
        // Check if spawnspots are set OK
        if (Spots == null) {
            Debug.LogError ("SpawnSpots aren't assigned!");
            return;
        }
    
        mySpotNumber = SpotNumber;
    
        // The player object for the network
        GameObject myPlayerGO = (GameObject)PhotonNetwork.Instantiate ("PlayerController", 
                                                                       Spots[SpotNumber].transform.position,
                                                                       Spots[SpotNumber].transform.rotation, 0);
    
        // Enable a disabled script for *this player only, or all would have the same camera, movement, etc
        //((MonoBehaviour)myPlayerGO.GetComponent("FPSInputController")).enabled = true;
    
        // Set a camera just for this player
        //myPlayerGO.transform.FindChild ("Main Camera").gameObject.SetActive (true);
    
        //standbyCamera.SetActive(false);
    }
    

    Note: If you have more than two players, it gets a lot more difficult. This code isn't optimized so maybe you'll find a better one, but it should give you the right idea.

    Please ask if anything isn't clear to you...