Photon Network (Clasic) Ghid pentru începători

Photon Network este un serviciu pentru Unity care permite dezvoltatorilor să creeze jocuri multiplayer în timp real.

Oferă un API puternic și ușor de utilizat, care îl face perfect chiar și pentru dezvoltatorii începători.

În această postare, vom rula prin descărcarea fișierelor necesare, configurarea Photon AppID și programarea unui exemplu simplu de multiplayer.

Partea 1: Configurarea rețelei fotonice

Primul pas este să descărcați pachetul Photon Network din Asset Store. Conține toate scripturile și fișierele necesare pentru integrarea multiplayer.

  • Deschideți-vă proiectul Unity apoi accesați Asset Store: (Fereastra -> General -> AssetStore) sau apăsați Ctrl+9
  • Căutați „Photon Unity Networking Classic - Free”, apoi faceți clic pe primul rezultat sau faceți clic aici
  • Importați pachetul Photon după ce descărcarea este terminată

  • După ce pachetul este importat, trebuie să creați un ID de aplicație Photon, acest lucru se face pe site-ul lor: https://www.photonengine.com/
  • Creați un cont nou (sau conectați-vă la contul dvs. existent)
  • Accesați pagina Aplicații făcând clic pe pictograma profilului și apoi pe "Your Applications" sau urmați acest link: https://dashboard.photonengine.com/en-US/PublicCloud
  • Pe pagina Aplicații, faceți clic "Create new app"

  • Pe pagina de creare, pentru Tipul fotonului selectați "Photon Realtime" și pentru Nume, introduceți orice nume, apoi faceți clic "Create"

După cum puteți vedea, aplicația este implicită la planul gratuit. Puteți citi mai multe despre planurile de preț aici

  • Odată ce aplicația este creată, copiați ID-ul aplicației aflat sub numele aplicației

  • Reveniți la proiectul dvs. Unity, apoi accesați Window -> Photon Unity Networking -> PUN Wizard
  • În PUN Wizard, faceți clic pe "Setup Project", inserați ID-ul aplicației, apoi faceți clic "Setup Project"
  • Rețeaua Photon este acum gata

Partea 2: Crearea unui joc multiplayer

Acum să trecem la partea în care creăm de fapt un joc multiplayer.

Modul în care este gestionat multiplayerul în Photon este:

  • În primul rând, ne conectăm la Regiunea Photon (ex. SUA Est, Europa, Asia etc.) care este cunoscută și sub numele de Lobby.
  • Odată ajuns în hol, solicităm toate camerele care sunt create în regiune, apoi ne putem alătura fie uneia dintre camere, fie să ne creăm propria cameră.
  • După ce ne-am alăturat camerei, solicităm o listă a jucătorilor conectați la cameră și le instanțiem instanțele Player, care sunt apoi sincronizate cu instanțele locale prin PhotonView.
  • Când cineva părăsește Camera, instanța sa este distrusă și este eliminat din Lista de jucători.

1. Crearea unui hol

Să începem prin a crea un Meniu Principal care va conține o logică de lobby (Rasfoirea camerelor existente, crearea de camere noi etc.).

  • Creați o scenă nouă și apelați-o "MainMenu"
  • Creați un nou script C# și numiți-l GameLobby
  • În scena MainMenu, creați un nou GameObject. Apelați-l "_GameLobby" și atașați-i scriptul GameLobby

Acum deschideți scriptul GameLobby.

Mai întâi, să creăm toate variabilele necesare:

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

Următorul lucru pe care trebuie să-l facem este să activăm Auto-Join Lobby and Lobby Statistics, acest lucru ne va permite să primim lista de camere. Acest lucru se face în void Start().

De asemenea, activăm AutomaticSyncScene, astfel încât scena să fie sincronizată automat odată ce ne alăturăm Camerei.

Și, în sfârșit, numim PhotonNetwork.ConnectUsingSettings pentru a vă conecta.

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

Pentru a ști dacă o conexiune la Photon Cloud a avut succes, trebuie să implementăm aceste 2 apeluri inverse: OnReceivedRoomListUpdate() și OnFailedToConnectToPhoton(parametri obiect).

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

Urmează partea interfață de utilizare, unde se fac navigarea camerei și crearea camerei:

Lobby-ul Photon Network

Și, în sfârșit, implementăm alte 4 apeluri inverse: OnPhotonCreateRoomFailed(), OnPhotonJoinRoomFailed(object[] cause), OnCreatedRoom() și OnJoinedRoom().

Aceste apeluri inverse sunt folosite pentru a determina dacă ne-am alăturat/creat camera sau dacă au existat probleme în timpul conexiunii.

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

Și iată scriptul final GameLobby.cs:

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. Crearea unui prefabricat Player

În jocurile Multiplayer, instanța Player are 2 părți: Locală și La distanță.

O instanță locală este controlată local (de noi).

Instanța la distanță, pe de altă parte, este o reprezentare locală a ceea ce face celălalt jucător. Ar trebui să fie neafectat de contribuția noastră.

Pentru a determina dacă instanța este locală sau la distanță, folosim o componentă PhotonView.

PhotonView acționează ca un mesager care primește și trimite valorile care trebuie sincronizate, de exemplu, poziție și rotație.

Deci, să începem prin a crea instanța de jucător (Dacă aveți deja instanța de jucător pregătită, puteți sări peste acest pas).

În cazul meu, instanța Player va fi un simplu cub care este mutat cu tastele W și S și rotit cu tastele A și D.

Instanță Photon Network Player

Și aici este un script de controler simplu:

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

Următorul pas este să adăugați o componentă PhotonView.

  • Adăugați o componentă PhotonView la Instanța Player
  • Creați un nou script C#, numiți-l PlayerNetworkSync și deschideți-l (acest script va fi folosit pentru a comunica prin PhotonView)

Primul lucru pe care trebuie să-l facem este să înlocuim MonoBehaviour cu Photon.MonoBehaviour. Acest pas este necesar pentru a putea folosi variabila photonView stocată în cache în loc să utilizați GetComponent<PhotonView>().

public class PlayerNetworkSync : Photon.MonoBehaviour

După aceea, putem trece pentru a crea toate variabilele necesare:

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

Apoi, în golul Start(), verificăm dacă playerul este Local sau La distanță utilizând 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);
            }
        }
    }

Sincronizarea reală se realizează prin apelul invers al PhotonView: OnPhotonSerializeView(flux PhotonStream, informații PhotonMessageInfo):

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

În acest caz, trimitem doar Poziția și Rotația jucătorului, dar puteți folosi exemplul de mai sus pentru a trimite orice valoare care este necesară pentru a fi sincronizată prin rețea, la o frecvență înaltă.

Valorile primite sunt apoi aplicate în 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);
        }
    }

Iată scriptul final PlayerNetworkSync.cs:

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);
        }
    }
}
  • Adăugați scriptul PlayerNetworkSync.cs la PlayerInstance și atribuiți-l Componentelor observate PhotonView.
  • Atribuiți PlayerCntroller.cs la "Local Scripts" și atribuiți GameObjects (pe care doriți să le dezactivați pentru jucătorii de la distanță) "Local Objects"

  • Salvați PlayerInstance în Prefab și mutați-l în folderul numit Resurse (Dacă nu există un astfel de folder, creați unul). Acest pas este necesar pentru a putea genera obiecte multiplayer prin rețea.

3. Crearea unui nivel de joc

GameLevel este o scenă care se încarcă după alăturarea camerei și este locul în care se întâmplă toată acțiunea.

  • Creați o scenă nouă și numiți-o "GameLevel" (sau dacă doriți să păstrați un alt nume, asigurați-vă că schimbați numele în această linie PhotonNetwork.LoadLevel("GameLevel"); la GameLobby.cs).

În cazul meu, voi folosi o scenă simplă cu un avion:

  • Acum creați un nou script și numiți-l RoomController. Acest script se va ocupa de logica din interiorul camerei (cum ar fi generarea jucătorilor, afișarea listei de jucători etc.).

Să începem prin a defini variabilele necesare:

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

Pentru a instanția prefabricatul Player, folosim 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);
    }

Și o interfață simplă cu un buton "Leave Room" și câteva elemente suplimentare, cum ar fi numele camerei și lista de jucători conectați:

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

Și, în sfârșit, implementăm un alt apel invers PhotonNetwork numit OnLeftRoom() care este apelat când părăsim Camera:

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

Și iată scriptul final RoomController.cs:

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");
    }
}
  • În cele din urmă, creați un nou GameObject în scena GameLevel și apelați-l "_RoomController"
  • Atașați scriptul RoomController la obiectul _RoomController
  • Atribuiți-i prefabricatul PlayerInstance și o transformare SpawnPoint, apoi salvați scena
  • Adăugați atât MainMenu, cât și GameLevel la setările de compilare.

4. Efectuarea unui test Build

Acum este timpul să faceți o construcție și să o testați:

Sharp Coder Video player

Totul funcționează conform așteptărilor!

Primă

RPC

În Photon Network, RPC înseamnă Remote Procedure Call, este folosit pentru a apela o funcție pe clienții la distanță care se află în aceeași cameră (puteți citi mai multe despre aceasta aici ).

RPC-urile au multe utilizări, de exemplu, să presupunem că trebuie să trimiteți un mesaj de chat tuturor jucătorilor din cameră. Cu RPC-uri, este ușor de făcut.

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

Observați [PunRPC] înainte de funcție. Acest atribut este necesar dacă intenționați să apelați funcția prin RPC-uri.

Pentru a apela funcțiile marcate ca RPC, aveți nevoie de un PhotonView. Exemplu de apel:

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

Sfat profesionist: dacă scriptul dvs. este un Photon.MonoBehaviour sau Photon.PunBehaviour, puteți utiliza: this.photonView.RPC().

Proprietăți personalizate

În Photon Network, Custom Properties este un Hashtable care poate fi atribuit Playerului sau Camerei.

Acest lucru este util atunci când trebuie să setați date persistente care nu trebuie modificate frecvent (de exemplu, numele echipei jucătorului, modul joc în cameră etc.).

Mai întâi, trebuie să definiți un Hashtable, care se face prin adăugarea liniei de mai jos la începutul scriptului:

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

Exemplul de mai jos setează proprietățile camerei numite "GameMode" și "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"]);

Proprietățile jucătorului sunt setate în mod similar:

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

Pentru a elimina o anumită proprietate, setați valoarea acesteia la null.

        //Remove property called "PlayerHP" from Player properties
        Hashtable setPlayerProperties = new Hashtable();
        setPlayerProperties.Add("PlayerHP", null);
        PhotonNetwork.player.SetCustomProperties(setPlayerProperties);
Articole sugerate
Creați un joc cu mașini multiplayer cu PUN 2
Tutorial online pentru clasament pentru Unity
Faceți un joc multiplayer în Unity folosind PUN 2
Crearea de jocuri multiplayer în rețea în Unity
Comprimarea datelor multiplayer și manipularea biților
PUN 2 Compensare lag
Unity Adăugând chat multiplayer în camerele PUN 2