Photon Network (Classic) Nybörjarguide

Photon Network är en tjänst för Unity som låter utvecklare skapa flerspelarspel i realtid.

Det ger ett kraftfullt och lättanvänt API som gör det perfekt även för nybörjare.

I det här inlägget kommer vi att köra genom att ladda ner de nödvändiga filerna, ställa in Photon AppID och programmera ett enkelt multiplayer-exempel.

Del 1: Konfigurera Photon Network

Det första steget är att ladda ner Photon Network-paketet från Asset Store. Den innehåller alla nödvändiga skript och filer för integration med flera spelare.

  • Öppna ditt Unity-projekt och gå sedan till Asset Store: (Fönster -> Allmänt -> AssetStore) eller tryck på Ctrl+9
  • Sök efter "Foton Unity Networking Classic - Gratis" och klicka sedan på det första resultatet eller klicka här
  • Importera Photon-paketet efter att nedladdningen är klar

  • Efter att paketet har importerats måste du skapa ett Photon App ID, detta görs på deras hemsida: https://www.photonengine.com/
  • Skapa ett nytt konto (eller logga in på ditt befintliga konto)
  • Gå till applikationssidan genom att klicka på profilikonen och sedan på "Your Applications" eller följ denna länk: https://dashboard.photonengine.com/en-US/PublicCloud
  • Klicka på sidan Applikationer "Create new app"

  • På sidan för att skapa, välj "Photon Realtime" för Photon Type och för Namn, skriv valfritt namn och klicka sedan på "Create"

Som du kan se använder applikationen gratisplanen som standard. Du kan läsa mer om prisplaner här

  • När applikationen har skapats kopierar du app-ID:t under appnamnet

  • Gå tillbaka till ditt Unity-projekt och gå sedan till Fönster -> Foton Unity Nätverk -> PUN Wizard
  • Klicka på "Setup Project" i PUN Wizard, klistra in ditt app-ID och klicka sedan "Setup Project"
  • Photon Network är nu redo

Del 2: Skapa ett spel för flera spelare

Låt oss nu gå till delen där vi faktiskt skapar ett spel för flera spelare.

Sättet multiplayer hanteras i Photon är:

  • Först ansluter vi till Photon Region (ex. USA East, Europa, Asien, etc.) som också är känd som Lobby.
  • Väl i lobbyn begär vi alla rum som skapas i regionen, sedan kan vi antingen gå med i ett av rummen eller skapa vårt eget rum.
  • Efter att vi gick med i rummet begär vi en lista över spelarna som är anslutna till rummet och instansierar deras Player-instanser, som sedan synkroniseras med deras lokala instanser via PhotonView.
  • När någon lämnar rummet förstörs deras instans och de tas bort från spelarlistan.

1. Skapa en lobby

Låt oss börja med att skapa en huvudmeny som kommer att innehålla en lobbylogik (bläddra i befintliga rum, skapa nya rum, etc.).

  • Skapa en ny scen och kalla den "MainMenu"
  • Skapa ett nytt C#-skript och kalla det GameLobby
  • Skapa ett nytt GameObject i MainMenu-scenen. Kalla det "_GameLobby" och bifoga GameLobby-skriptet till det

Öppna nu GameLobby-skriptet.

Låt oss först skapa alla nödvändiga 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;

Nästa sak vi behöver göra är att aktivera Auto-Join Lobby och Lobby Stats, detta gör att vi kan ta emot rumslistan. Detta görs i tomrummet Start().

Dessutom aktiverar vi automatisk SyncScene så att scenen synkroniseras automatiskt när vi går med i rummet.

Och slutligen kallar vi PhotonNetwork.ConnectUsingSettings för att ansluta.

    // 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);
        }
    }

För att veta om en anslutning till Photon Cloud lyckades måste vi implementera dessa två callbacks: OnReceivedRoomListUpdate() och OnFailedToConnectToPhoton(objektparametrar).

    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();
    }

Nästa är UI-delen, där rumssökning och skapande av rum görs:

Photon Network lobby

Och slutligen implementerar vi ytterligare fyra callbacks: OnPhotonCreateRoomFailed(), OnPhotonJoinRoomFailed(objekt[] orsak), OnCreatedRoom() och OnJoinedRoom().

Dessa återuppringningar används för att avgöra om vi gick med/skapade rummet eller om det fanns några problem under anslutningen.

    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");
    }

Och här är det sista GameLobby.cs-skriptet:

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. Skapa en prefab för spelare

I spel med flera spelare har Player-instansen två sidor: Lokal och Fjärr.

En lokal instans kontrolleras lokalt (av oss).

Fjärrinstans, å andra sidan, är en lokal representation av vad den andra spelaren gör. Det bör vara opåverkat av vår input.

För att avgöra om instansen är lokal eller fjärrstyrd använder vi en PhotonView-komponent.

PhotonView fungerar som en budbärare som tar emot och skickar de värden som behöver synkas, till exempel position och rotation.

Så låt oss börja med att skapa spelarinstansen (om du redan har din spelarinstans redo kan du hoppa över det här steget).

I mitt fall kommer Player-instansen att vara en enkel kub som flyttas med W- och S-tangenterna och roteras med A- och D-tangenterna.

Photon Network Player-instans

Och här är ett enkelt kontrollerskript:

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);
        }
    }
}

Nästa steg är att lägga till en PhotonView-komponent.

  • Lägg till en PhotonView-komponent till Player Instance
  • Skapa ett nytt C#-skript, kalla det PlayerNetworkSync och öppna det (det här skriptet kommer att användas för att kommunicera via PhotonView)

Det första vi behöver göra är att ersätta MonoBehaviour med Photon.MonoBehaviour. Detta steg är nödvändigt för att kunna använda den cachade photonView-variabeln istället för att använda GetComponent<PhotonView>().

public class PlayerNetworkSync : Photon.MonoBehaviour

Efter det kan vi flytta för att skapa alla nödvändiga 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;

Sedan kontrollerar vi i tomrummet Start() om spelaren är Local eller Remote genom att använda 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);
            }
        }
    }

Den faktiska synkroniseringen görs genom PhotonViews återuppringning: OnPhotonSerializeView(PhotonStream-ström, 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 det här fallet skickar vi bara spelaren Position och Rotation, men du kan använda exemplet ovan för att skicka valfritt värde som behövs för att synkroniseras över nätverket, med hög frekvens.

Mottagna värden tillämpas sedan i 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);
        }
    }

Här är det sista PlayerNetworkSync.cs-skriptet:

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);
        }
    }
}
  • Lägg till PlayerNetworkSync.cs-skriptet till PlayerInstance och tilldela det till PhotonView Observed Components.
  • Tilldela PlayerCntroller.cs till "Local Scripts" och tilldela GameObjects (som du vill ska inaktiveras för fjärrspelare) till "Local Objects"

  • Spara PlayerInstance till Prefab och flytta den till mappen som heter Resources (Om det inte finns någon sådan mapp, skapa en). Detta steg är nödvändigt för att kunna skapa flerspelarobjekt över nätverket.

3. Skapa en spelnivå

GameLevel är en scen som laddas efter att ha gått med i rummet och det är där all action sker.

  • Skapa en ny scen och kalla den "GameLevel" (Eller om du vill behålla ett annat namn, se till att ändra namnet på den här raden PhotonNetwork.LoadLevel("GameLevel"); på GameLobby.cs).

I mitt fall kommer jag att använda en enkel scen med ett plan:

  • Skapa nu ett nytt skript och kalla det RoomController. Detta skript kommer att hantera logiken i rummet (som att skapa spelarna, visa spelarlistan, etc.).

Låt oss börja med att definiera de nödvändiga variablerna:

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

För att instansiera Player prefab använder 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);
    }

Och ett enkelt användargränssnitt med en "Leave Room"-knapp och några ytterligare element som rumsnamn och listan över anslutna spelare:

    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);
        }
    }

Och slutligen implementerar vi ytterligare ett PhotonNetwork callback som heter OnLeftRoom() som anropas när vi lämnar rummet:

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

Och här är det sista RoomController.cs-skriptet:

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");
    }
}
  • Slutligen, skapa ett nytt GameObject i GameLevel-scenen och kalla det "_RoomController"
  • Bifoga RoomController-skriptet till _RoomController-objektet
  • Tilldela PlayerInstance prefab och en SpawnPoint Transform till den och spara sedan scenen
  • Lägg till både MainMenu och GameLevel till bygginställningarna.

4. Göra ett testbygge

Nu är det dags att bygga och testa den:

Sharp Coder Videospelare

Allt fungerar som förväntat!

Bonus

RPC

I Photon Network står RPC för Remote Procedure Call, det används för att anropa en funktion på Remote-klienter som finns i samma rum (du kan läsa mer om det här ).

RPC:er har många användningsområden, låt oss till exempel säga att du behöver skicka ett chattmeddelande till alla spelare i rummet. Med RPC:er är det lätt att göra.

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

Lägg märke till [PunRPC] före funktionen. Detta attribut är nödvändigt om du planerar att anropa funktionen via RPC:er.

För att anropa funktionerna markerade som RPC behöver du en PhotonView. Exempelsamtal:

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

Proffstips: Om ditt skript är ett Photon.MonoBehaviour eller Photon.PunBehaviour kan du använda: this.photonView.RPC().

Anpassade egenskaper

I Photon Network är Custom Properties en hashtabell som kan tilldelas spelaren eller rummet.

Detta är användbart när du behöver ställa in beständiga data som inte behöver ändras ofta (t.ex. spelarens lagnamn, rumsspelsläge, etc.).

Först måste du definiera en hashtabell, vilket görs genom att lägga till raden nedan i början av skriptet:

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

Exemplet nedan anger rumsegenskaperna som heter "GameMode" och "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"]);

Spelaregenskaper ställs in på liknande sätt:

        //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"]);

För att ta bort specifik egenskap ställ bara in dess värde till null.

        //Remove property called "PlayerHP" from Player properties
        Hashtable setPlayerProperties = new Hashtable();
        setPlayerProperties.Add("PlayerHP", null);
        PhotonNetwork.player.SetCustomProperties(setPlayerProperties);
Föreslagna artiklar
Gör ett bilspel för flera spelare med PUN 2
Unity Lägger till flerspelarchatt till PUN 2-rummen
Synkronisera stela kroppar över nätverk med PUN 2
Skapa ett multiplayer-spel i Unity med PUN 2
Bygga nätverksspel för flera spelare i Unity
Multiplayer-datakomprimering och bitmanipulation
Handledning för Unity Online Leaderboard