Photon Network (klassisk) begyndervejledning

Photon Network er en tjeneste for Unity, der giver udviklere mulighed for at skabe multiplayer-spil i realtid.

Det giver en kraftfuld og brugervenlig API, som gør den perfekt, selv for nybegyndere.

I dette indlæg kører vi gennem download af de nødvendige filer, opsætning af Photon AppID og programmering af et simpelt multiplayer-eksempel.

Del 1: Opsætning af Photon Network

Det første trin er at downloade Photon Network-pakken fra Asset Store. Den indeholder alle de nødvendige scripts og filer til multiplayer-integration.

  • Åbn dit Unity-projekt og gå derefter til Asset Store: (Vindue -> Generelt -> AssetStore), eller tryk på Ctrl+9
  • Søg efter "Photon Unity Networking Classic - Gratis", og klik derefter på det første resultat eller klik her
  • Importer Photon-pakken efter download er færdig

  • På oprettelsessiden, for Photon Type, vælg "Photon Realtime" og for navnet, skriv et hvilket som helst navn og klik derefter "Create"

Som du kan se, er applikationen som standard den gratis plan. Du kan læse mere om prisplaner her

  • Når applikationen er oprettet, skal du kopiere app-id'et, der er placeret under app-navnet

  • Gå tilbage til dit Unity-projekt, og gå derefter til Window -> Photon Unity Networking -> PUN Wizard
  • Klik på "Setup Project" i PUN-guiden, indsæt dit app-id og klik derefter "Setup Project"
  • Photon Network er nu klar

Del 2: Oprettelse af et multiplayer-spil

Lad os nu gå til den del, hvor vi faktisk skaber et multiplayer-spil.

Måden multiplayer håndteres i Photon er:

  • Først forbinder vi til Photon-regionen (f.eks. USA Øst, Europa, Asien osv.), som også er kendt som Lobby.
  • Når vi først er i lobbyen, anmoder vi om alle de rum, der er oprettet i regionen, så kan vi enten tilslutte os et af værelserne eller oprette vores eget værelse.
  • Efter at vi tiltrådte rummet, anmoder vi om en liste over de spillere, der er forbundet til rummet og instansierer deres afspillerforekomster, som derefter synkroniseres med deres lokale forekomster gennem PhotonView.
  • Når nogen forlader rummet, bliver deres instans ødelagt, og de fjernes fra spillerlisten.

1. Oprettelse af en lobby

Lad os starte med at oprette en hovedmenu, som vil indeholde en lobbylogik (gennemgang af eksisterende rum, oprettelse af nye rum osv.).

  • Opret en ny scene og kald den "MainMenu"
  • Opret et nyt C#-script og kald det GameLobby
  • Opret et nyt GameObject i MainMenu-scenen. Kald det "_GameLobby" og vedhæft GameLobby-scriptet til det

Åbn nu GameLobby-scriptet.

Lad os først oprette alle de nødvendige variabler:

    //Our player name
    string playerName = "Player 1";
    //This client's version number. Users are separated from each other by gameversion (which allows you to make breaking changes).
    string gameVersion = "0.9";
    //The list of created rooms
    RoomInfo[] createdRooms = new RoomInfo[0];
    //Use this name when creating a Room
    string roomName = "Room 1";
    Vector2 roomListScroll = Vector2.zero;
    bool joiningRoom = false;

Den næste ting, vi skal gøre, er at aktivere Auto-Join Lobby og Lobby Stats, dette vil tillade os at modtage værelseslisten. Dette gøres i det tomme Start().

Desuden aktiverer vi automatisk SyncScene, så scenen automatisk synkroniseres, når vi tilmelder os rummet.

Og til sidst kalder vi PhotonNetwork.ConnectUsingSettings for at forbinde.

    // Use this for initialization
    void Start()
    {
        //Automatically join Lobby after we connect to Photon Region
        PhotonNetwork.PhotonServerSettings.JoinLobby = true;
        //Enable Lobby Stats to receive the list of Created rooms
        PhotonNetwork.PhotonServerSettings.EnableLobbyStatistics = true;
        //This makes sure we can use PhotonNetwork.LoadLevel() on the master client and all clients in the same room sync their level automatically
        PhotonNetwork.automaticallySyncScene = true;

        if (!PhotonNetwork.connected)
        {
            // Connect to the photon master-server. We use the settings saved in PhotonServerSettings (a .asset file in this project)
            PhotonNetwork.ConnectUsingSettings(gameVersion);
        }
    }

For at vide, om en forbindelse til Photon Cloud lykkedes, skal vi implementere disse 2 tilbagekald: OnReceivedRoomListUpdate() og OnFailedToConnectToPhoton(objektparametre).

    void OnFailedToConnectToPhoton(object parameters)
    {
        Debug.Log("OnFailedToConnectToPhoton. StatusCode: " + parameters + " ServerAddress: " + PhotonNetwork.ServerAddress);
        //Try to connect again
        PhotonNetwork.ConnectUsingSettings(gameVersion);
    }

    void OnReceivedRoomListUpdate()
    {
        Debug.Log("We have received the Room list");
        //After this callback, PhotonNetwork.GetRoomList() becomes available
        createdRooms = PhotonNetwork.GetRoomList();
    }

Dernæst er UI-delen, hvor rumbrowsing og rumoprettelse udføres:

Photon Network lobby

Og til sidst implementerer vi yderligere 4 tilbagekald: OnPhotonCreateRoomFailed(), OnPhotonJoinRoomFailed(objekt[] årsag), OnCreatedRoom() og OnJoinedRoom().

Disse tilbagekald bruges til at afgøre, om vi sluttede os til/oprettede rummet, eller om der var problemer under forbindelsen.

    void OnPhotonCreateRoomFailed()
    {
        Debug.Log("OnPhotonCreateRoomFailed got called. This can happen if the room exists (even if not visible). Try another room name.");
        joiningRoom = false;
    }

    void OnPhotonJoinRoomFailed(object[] cause)
    {
        Debug.Log("OnPhotonJoinRoomFailed got called. This can happen if the room is not existing or full or closed.");
        joiningRoom = false;
    }

    void OnCreatedRoom()
    {
        Debug.Log("OnCreatedRoom");
        //Set our player name
        PhotonNetwork.playerName = playerName;
        //Load the Scene called GameLevel (Make sure it's added to build settings)
        PhotonNetwork.LoadLevel("GameLevel");
    }

    void OnJoinedRoom()
    {
        Debug.Log("OnJoinedRoom");
    }

Og her er det sidste GameLobby.cs-script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameLobby : MonoBehaviour
{
    //Our player name
    string playerName = "Player 1";
    //This client's version number. Users are separated from each other by gameversion (which allows you to make breaking changes).
    string gameVersion = "0.9";
    //The list of created rooms
    RoomInfo[] createdRooms = new RoomInfo[0];
    //Use this name when creating a Room
    string roomName = "Room 1";
    Vector2 roomListScroll = Vector2.zero;
    bool joiningRoom = false;

    // Use this for initialization
    void Start()
    {
        //Automatically join Lobby after we connect to Photon Region
        PhotonNetwork.PhotonServerSettings.JoinLobby = true;
        //Enable Lobby Stats to receive the list of Created rooms
        PhotonNetwork.PhotonServerSettings.EnableLobbyStatistics = true;
        //This makes sure we can use PhotonNetwork.LoadLevel() on the master client and all clients in the same room sync their level automatically
        PhotonNetwork.automaticallySyncScene = true;

        if (!PhotonNetwork.connected)
        {
            // Connect to the photon master-server. We use the settings saved in PhotonServerSettings (a .asset file in this project)
            PhotonNetwork.ConnectUsingSettings(gameVersion);
        }
    }

    void OnFailedToConnectToPhoton(object parameters)
    {
        Debug.Log("OnFailedToConnectToPhoton. StatusCode: " + parameters + " ServerAddress: " + PhotonNetwork.ServerAddress);
        //Try to connect again
        PhotonNetwork.ConnectUsingSettings(gameVersion);
    }

    void OnReceivedRoomListUpdate()
    {
        Debug.Log("We have received the Room list");
        //After this callback, PhotonNetwork.GetRoomList() becomes available
        createdRooms = PhotonNetwork.GetRoomList();
    }

    void OnGUI()
    {
        GUI.Window(0, new Rect(Screen.width/2 - 450, Screen.height/2 - 200, 900, 400), LobbyWindow, "Lobby");
    }

    void LobbyWindow(int index)
    {
        //Connection Status and Room creation Button
        GUILayout.BeginHorizontal();

            GUILayout.Label("Status: " + PhotonNetwork.connectionStateDetailed);

            if(joiningRoom || !PhotonNetwork.connected)
            {
                GUI.enabled = false;
            }

            GUILayout.FlexibleSpace();

            //Room name text field
            roomName = GUILayout.TextField(roomName, GUILayout.Width(250));

            if (GUILayout.Button("Create Room", GUILayout.Width(125)))
            {
                if (roomName != "")
                {
                    joiningRoom = true;

                    RoomOptions roomOptions = new RoomOptions();
                    roomOptions.IsOpen = true;
                    roomOptions.IsVisible = true;
                    roomOptions.MaxPlayers = (byte)10; //Set any number

                    PhotonNetwork.JoinOrCreateRoom(roomName, roomOptions, TypedLobby.Default);
                }
            }

        GUILayout.EndHorizontal();

        //Scroll through available rooms
        roomListScroll = GUILayout.BeginScrollView(roomListScroll, true, true);

            if(createdRooms.Length == 0)
            {
                GUILayout.Label("No Rooms were created yet...");
            }
            else
            {
                for(int i = 0; i < createdRooms.Length; i++)
                {
                    GUILayout.BeginHorizontal("box");
                    GUILayout.Label(createdRooms[i].Name, GUILayout.Width(400));
                    GUILayout.Label(createdRooms[i].PlayerCount + "/" + createdRooms[i].MaxPlayers);

                    GUILayout.FlexibleSpace();
                
                    if (GUILayout.Button("Join Room"))
                    {
                        joiningRoom = true;

                        //Set our Player name
                        PhotonNetwork.playerName = playerName;

                        //Join the Room
                        PhotonNetwork.JoinRoom(createdRooms[i].Name);
                    }
                    GUILayout.EndHorizontal();
                }
            }

        GUILayout.EndScrollView();

        //Set player name and Refresh Room button
        GUILayout.BeginHorizontal();

            GUILayout.Label("Player Name: ", GUILayout.Width(85));
            //Player name text field
            playerName = GUILayout.TextField(playerName, GUILayout.Width(250));

            GUILayout.FlexibleSpace();

            GUI.enabled = PhotonNetwork.connectionState != ConnectionState.Connecting && !joiningRoom;
            if (GUILayout.Button("Refresh", GUILayout.Width(100)))
            {
                if (PhotonNetwork.connected)
                {
                    //We are already connected, simply update the Room list
                    createdRooms = PhotonNetwork.GetRoomList();
                }
                else
                {
                    //We are not connected, estabilish a new connection
                    PhotonNetwork.ConnectUsingSettings(gameVersion);
                }
            }

        GUILayout.EndHorizontal();

        if (joiningRoom)
        {
            GUI.enabled = true;
            GUI.Label(new Rect(900/2 - 50, 400/2 - 10, 100, 20), "Connecting...");
        }
    }

    void OnPhotonCreateRoomFailed()
    {
        Debug.Log("OnPhotonCreateRoomFailed got called. This can happen if the room exists (even if not visible). Try another room name.");
        joiningRoom = false;
    }

    void OnPhotonJoinRoomFailed(object[] cause)
    {
        Debug.Log("OnPhotonJoinRoomFailed got called. This can happen if the room is not existing or full or closed.");
        joiningRoom = false;
    }

    void OnCreatedRoom()
    {
        Debug.Log("OnCreatedRoom");
        //Set our player name
        PhotonNetwork.playerName = playerName;
        //Load the Scene called GameLevel (Make sure it's added to build settings)
        PhotonNetwork.LoadLevel("GameLevel");
    }

    void OnJoinedRoom()
    {
        Debug.Log("OnJoinedRoom");
    }
}

2. Oprettelse af en Player prefab

I multiplayer-spil har Player-instansen 2 sider: Lokal og Remote.

En lokal instans kontrolleres lokalt (af os).

Fjerninstans er på den anden side en lokal repræsentation af, hvad den anden spiller gør. Det burde være upåvirket af vores input.

For at afgøre, om forekomsten er lokal eller ekstern, bruger vi en PhotonView-komponent.

PhotonView fungerer som en messenger, der modtager og sender de værdier, der skal synkroniseres, for eksempel position og rotation.

Så lad os starte med at oprette afspillerinstansen (hvis du allerede har din afspillerinstans klar, kan du springe dette trin over).

I mit tilfælde vil Player-instansen være en simpel terning, der flyttes med tasterne W og S og roteres med tasterne A og D.

Photon Network Player Forekomst

Og her er et simpelt controller-script:

PlayerController.cs

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    // Update is called once per frame
    void Update()
    {
        //Move Front/Back
        if (Input.GetKey(KeyCode.W))
        {
            transform.Translate(transform.forward * Time.deltaTime * 2.45f, Space.World);
        }
        else if (Input.GetKey(KeyCode.S))
        {
            transform.Translate(-transform.forward * Time.deltaTime * 2.45f, Space.World);
        }

        //Rotate Left/Right
        if (Input.GetKey(KeyCode.A))
        {
            transform.Rotate(new Vector3(0, -14, 0) * Time.deltaTime * 4.5f, Space.Self);
        }
        else if (Input.GetKey(KeyCode.D))
        {
            transform.Rotate(new Vector3(0, 14, 0) * Time.deltaTime * 4.5f, Space.Self);
        }
    }
}

Det næste trin er at tilføje en PhotonView-komponent.

  • Tilføj en PhotonView-komponent til Player Instance
  • Opret et nyt C#-script, kald det PlayerNetworkSync, og åbn det (dette script vil blive brugt til at kommunikere gennem PhotonView)

Det første, vi skal gøre, er at erstatte MonoBehaviour med Photon.MonoBehaviour. Dette trin er nødvendigt for at kunne bruge den cachelagrede photonView-variabel i stedet for at bruge GetComponent<PhotonView>().

public class PlayerNetworkSync : Photon.MonoBehaviour

Derefter kan vi flytte for at oprette alle de nødvendige variabler:

    //List of the scripts that should only be active for the local player (ex. PlayerController, MouseLook etc.)
    public MonoBehaviour[] localScripts;
    //List of the GameObjects that should only be active for the local player (ex. Camera, AudioListener etc.)
    public GameObject[] localObjects;
    //Values that will be synced over network
    Vector3 latestPos;
    Quaternion latestRot;

Så i tomrummet Start() tjekker vi, om afspilleren er lokal eller ekstern ved at bruge photonView.isMine:

    // Use this for initialization
    void Start()
    {
        if (photonView.isMine)
        {
            //Player is local
        }
        else
        {
            //Player is Remote
            for(int i = 0; i < localScripts.Length; i++)
            {
                localScripts[i].enabled = false;
            }
            for (int i = 0; i < localObjects.Length; i++)
            {
                localObjects[i].SetActive(false);
            }
        }
    }

Selve synkroniseringen udføres gennem PhotonViews tilbagekald: OnPhotonSerializeView(PhotonStream-stream, PhotonMessageInfo info):

    void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.isWriting)
        {
            //We own this player: send the others our data
            stream.SendNext(transform.position);
            stream.SendNext(transform.rotation);
        }
        else
        {
            //Network player, receive data
            latestPos = (Vector3)stream.ReceiveNext();
            latestRot = (Quaternion)stream.ReceiveNext();
        }
    }

I dette tilfælde sender vi kun afspillerens position og rotation, men du kan bruge eksemplet ovenfor til at sende enhver værdi, der er nødvendig for at blive synkroniseret over netværket, ved en høj frekvens.

Modtagne værdier anvendes derefter i den void Update():

    // Update is called once per frame
    void Update()
    {
        if (!photonView.isMine)
        {
            //Update remote player (smooth this, this looks good, at the cost of some accuracy)
            transform.position = Vector3.Lerp(transform.position, latestPos, Time.deltaTime * 5);
            transform.rotation = Quaternion.Lerp(transform.rotation, latestRot, Time.deltaTime * 5);
        }
    }

Her er det sidste PlayerNetworkSync.cs-script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerNetworkSync : Photon.MonoBehaviour
{
    //List of the scripts that should only be active for the local player (ex. PlayerController, MouseLook etc.)
    public MonoBehaviour[] localScripts;
    //List of the GameObjects that should only be active for the local player (ex. Camera, AudioListener etc.)
    public GameObject[] localObject;
    //Values that will be synced over network
    Vector3 latestPos;
    Quaternion latestRot;

    // Use this for initialization
    void Start()
    {
        if (photonView.isMine)
        {
            //Player is local
        }
        else
        {
            //Player is Remote
            for(int i = 0; i < localScripts.Length; i++)
            {
                localScripts[i].enabled = false;
            }
            for (int i = 0; i < localObject.Length; i++)
            {
                localObject[i].SetActive(false);
            }
        }
    }

    void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.isWriting)
        {
            //We own this player: send the others our data
            stream.SendNext(transform.position);
            stream.SendNext(transform.rotation);
        }
        else
        {
            //Network player, receive data
            latestPos = (Vector3)stream.ReceiveNext();
            latestRot = (Quaternion)stream.ReceiveNext();
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (!photonView.isMine)
        {
            //Update remote player (smooth this, this looks good, at the cost of some accuracy)
            transform.position = Vector3.Lerp(transform.position, latestPos, Time.deltaTime * 5);
            transform.rotation = Quaternion.Lerp(transform.rotation, latestRot, Time.deltaTime * 5);
        }
    }
}
  • Tilføj PlayerNetworkSync.cs-scriptet til PlayerInstance og tildel det til PhotonView Observed Components.
  • Tildel PlayerCntroller.cs til "Local Scripts" og tildel GameObjects (som du ønsker skal deaktiveres for Remote-spillere) til "Local Objects"

  • Gem PlayerInstance til Prefab og flyt den til mappen kaldet Ressourcer (Hvis der ikke er en sådan mappe, opret en). Dette trin er nødvendigt for at kunne skabe multiplayer-objekter over netværket.

3. Oprettelse af et spilniveau

GameLevel er en scene, der indlæses efter at have tilmeldt sig rummet, og det er her al handlingen sker.

  • Opret en ny scene og kald den "GameLevel" (Eller hvis du vil beholde et andet navn, så sørg for at ændre navnet på denne linje PhotonNetwork.LoadLevel("GameLevel"); på GameLobby.cs).

I mit tilfælde vil jeg bruge en simpel scene med et fly:

  • Opret nu et nyt script og kald det RoomController. Dette script vil håndtere logikken inde i rummet (som at skabe spillerne, vise spillerlisten osv.).

Lad os starte med at definere de nødvendige variabler:

    //Player instance prefab, must be located in the Resources folder
    public GameObject playerPrefab;
    //Player spawn point
    public Transform spawnPoint;

For at instantiere afspillerens præfabrikat bruger vi PhotonNetwork.Instantiate:

    // Use this for initialization
    void Start()
    {
        //In case we started this demo with the wrong scene being active, simply load the menu scene
        if (!PhotonNetwork.connected)
        {
            UnityEngine.SceneManagement.SceneManager.LoadScene("MainMenu");
            return;
        }

        //We're in a room. spawn a character for the local player. it gets synced by using PhotonNetwork.Instantiate
        PhotonNetwork.Instantiate(playerPrefab.name, spawnPoint.position, Quaternion.identity, 0);
    }

Og en simpel brugergrænseflade med en "Leave Room"-knap og nogle yderligere elementer såsom rumnavn og listen over tilsluttede spillere:

    void OnGUI()
    {
        if (PhotonNetwork.room == null)
            return;

        //Leave this Room
        if (GUI.Button(new Rect(5, 5, 125, 25), "Leave Room"))
        {
            PhotonNetwork.LeaveRoom();
        }

        //Show the Room name
        GUI.Label(new Rect(135, 5, 200, 25), PhotonNetwork.room.Name);

        //Show the list of the players connected to this Room
        for (int i = 0; i < PhotonNetwork.playerList.Length; i++)
        {
            //Show if this player is a Master Client. There can only be one Master Client per Room so use this to define the authoritative logic etc.)
            string isMasterClient = (PhotonNetwork.playerList[i].IsMasterClient ? ": MasterClient" : "");
            GUI.Label(new Rect(5, 35 + 30 * i, 200, 25), PhotonNetwork.playerList[i].NickName + isMasterClient);
        }
    }

Og endelig implementerer vi endnu et PhotonNetwork-tilbagekald kaldet OnLeftRoom(), som kaldes, når vi forlader rummet:

    void OnLeftRoom()
    {
        //We have left the Room, return to the MainMenu
        UnityEngine.SceneManagement.SceneManager.LoadScene("MainMenu");
    }

Og her er det sidste RoomController.cs-script:

using UnityEngine;

public class RoomController : MonoBehaviour
{
    //Player instance prefab, must be located in the Resources folder
    public GameObject playerPrefab;
    //Player spawn point
    public Transform spawnPoint;

    // Use this for initialization
    void Start()
    {
        //In case we started this demo with the wrong scene being active, simply load the menu scene
        if (!PhotonNetwork.connected)
        {
            UnityEngine.SceneManagement.SceneManager.LoadScene("MainMenu");
            return;
        }

        //We're in a room. spawn a character for the local player. it gets synced by using PhotonNetwork.Instantiate
        PhotonNetwork.Instantiate(playerPrefab.name, spawnPoint.position, Quaternion.identity, 0);
    }

    void OnGUI()
    {
        if (PhotonNetwork.room == null)
            return;

        //Leave this Room
        if (GUI.Button(new Rect(5, 5, 125, 25), "Leave Room"))
        {
            PhotonNetwork.LeaveRoom();
        }

        //Show the Room name
        GUI.Label(new Rect(135, 5, 200, 25), PhotonNetwork.room.Name);

        //Show the list of the players connected to this Room
        for (int i = 0; i < PhotonNetwork.playerList.Length; i++)
        {
            //Show if this player is a Master Client. There can only be one Master Client per Room so use this to define the authoritative logic etc.)
            string isMasterClient = (PhotonNetwork.playerList[i].IsMasterClient ? ": MasterClient" : "");
            GUI.Label(new Rect(5, 35 + 30 * i, 200, 25), PhotonNetwork.playerList[i].NickName + isMasterClient);
        }
    }

    void OnLeftRoom()
    {
        //We have left the Room, return to the MainMenu
        UnityEngine.SceneManagement.SceneManager.LoadScene("MainMenu");
    }
}
  • Til sidst skal du oprette et nyt GameObject i GameLevel-scenen og kalde det "_RoomController"
  • Vedhæft RoomController-scriptet til _RoomController-objektet
  • Tildel PlayerInstance-præfabrikken og en SpawnPoint-transformation til den, og gem derefter scenen
  • Tilføj både MainMenu og GameLevel til Build-indstillingerne.

4. Lav en test Build

Nu er det tid til at lave en build og teste den:

Sharp Coder Videoafspiller

Alt fungerer som forventet!

Bonus

RPC

I Photon Network står RPC for Remote Procedure Call, det bruges til at kalde en funktion på Remote-klienter, der er i samme rum (Du kan læse mere om det her ).

RPC'er har mange anvendelsesmuligheder, lad os f.eks. sige, at du skal sende en chatbesked til alle spillerne i rummet. Med RPC'er er det nemt at gøre.

[PunRPC]
void ChatMessage(string senderName, string messageText)
{
    Debug.Log(string.Format("{0}: {1}", senderName, messageText));
}

Læg mærke til [PunRPC] før funktionen. Denne egenskab er nødvendig, hvis du planlægger at kalde funktionen via RPC'er.

For at kalde de funktioner, der er markeret som RPC, skal du bruge en PhotonView. Eksempel opkald:

PhotonView photonView = PhotonView.Get(this);
photonView.RPC("ChatMessage", PhotonTargets.All, PhotonNetwork.playerName, "Some message");

Professionelt tip: Hvis dit script er et Photon.MonoBehaviour eller Photon.PunBehaviour, kan du bruge: this.photonView.RPC().

Brugerdefinerede egenskaber

I Photon Network er Custom Properties en hashtabel, der kan tildeles til afspilleren eller rummet.

Dette er nyttigt, når du har brug for at indstille vedvarende data, som ikke skal ændres ofte (f.eks. spillerholdsnavn, rumspiltilstand osv.).

Først skal du definere en hashtabel, hvilket gøres ved at tilføje linjen nedenfor i begyndelsen af ​​scriptet:

//Replace default Hashtables with Photon hashtables
using Hashtable = ExitGames.Client.Photon.Hashtable; 

Eksemplet nedenfor angiver rumegenskaberne kaldet "GameMode" og "AnotherProperty":

        //Set Room properties (Only Master Client is allowed to set Room properties)
        if (PhotonNetwork.isMasterClient)
        {
            Hashtable setRoomProperties = new Hashtable();
            setRoomProperties.Add("GameMode", "FFA");
            setRoomProperties.Add("AnotherProperty", "Test");
            PhotonNetwork.room.SetCustomProperties(setRoomProperties);
        }

        //Will print "FFA"
        print((string)PhotonNetwork.room.CustomProperties["GameMode"]);
        //Will print "Test"
        print((string)PhotonNetwork.room.CustomProperties["AnotherProperty"]);

Spilleregenskaber er indstillet på samme måde:

        //Set our Player's property
        Hashtable setPlayerProperties = new Hashtable();
        setPlayerProperties.Add("PlayerHP", (float)100);
        PhotonNetwork.player.SetCustomProperties(setPlayerProperties);

        //Will print "100"
        print((float)PhotonNetwork.player.CustomProperties["PlayerHP"]);

For at fjerne specifik egenskab skal du blot sætte dens værdi til null.

        //Remove property called "PlayerHP" from Player properties
        Hashtable setPlayerProperties = new Hashtable();
        setPlayerProperties.Add("PlayerHP", null);
        PhotonNetwork.player.SetCustomProperties(setPlayerProperties);
Foreslåede artikler
Lav et multiplayer bilspil med PUN 2
Opbygning af multiplayer-netværksspil i Unity
Unity tilføjer multiplayer-chat til PUN 2-rummene
Synkroniser rigidbodies over netværk ved hjælp af PUN 2
Lav et multiplayer-spil i Unity ved hjælp af PUN 2
Multiplayer datakomprimering og bitmanipulation
Unity Online Leaderboard-vejledning