Guide du débutant Photon Network (classique)

Photon Network est un service pour Unity qui permet aux développeurs de créer des jeux multijoueurs en temps réel.

Il fournit une API puissante et facile à utiliser, ce qui le rend parfait même pour les développeurs novices.

Dans cet article, nous allons télécharger les fichiers nécessaires, configurer Photon AppID et programmer un exemple multijoueur simple.

Partie 1: Configuration du réseau de photons

La première étape consiste à télécharger le package Photon Network à partir du Asset Store. Il contient tous les scripts et fichiers nécessaires à l'intégration multijoueur.

  • Ouvrez votre Unity projet puis allez dans la Asset Store: (Fenêtre -> Général -> AssetStore ) ou appuyez sur Ctrl+9
  • Recherchez "Photon Unity Networking Classic - Free" puis cliquez sur le premier résultat ou cliquez ici
  • Importez le package Photon une fois le téléchargement terminé

  • Une fois le package importé, vous devez créer un ID d'application Photon, cela se fait sur leur site Web: https://www.photonengine.com/
  • Créez un nouveau compte (ou connectez-vous à votre compte existant)
  • Accédez à la page Applications en cliquant sur l'icône de profil, puis sur "Your Applications" ou suivez ce lien: https://dashboard.photonengine.com/en-US/PublicCloud
  • Sur la page Candidatures, cliquez "Create new app"

  • Sur la page de création, pour Photon Type sélectionnez "Photon Realtime" et pour le Nom, tapez n'importe quel nom puis cliquez sur "Create"

Comme vous pouvez le voir, l'application utilise par défaut le plan gratuit. Vous pouvez en savoir plus sur les forfaits ici

  • Une fois l'application créée, copiez l'identifiant de l'application situé sous le nom de l'application

  • Retournez à votre projet Unity puis allez dans Fenêtre -> Photon Unity Mise en réseau -> Assistant PUN
  • Dans l'assistant PUN, cliquez sur "Setup Project", collez votre ID d'application, puis cliquez sur "Setup Project"
  • Le Photon Network est maintenant prêt

Partie 2: Création d'un jeu multijoueur

Passons maintenant à la partie où nous créons réellement un jeu multijoueur.

La façon dont le multijoueur est géré dans Photon est:

  • Tout d'abord, nous nous connectons à la région Photon (ex. USA Est, Europe, Asie, etc.) qui est également connue sous le nom de Lobby.
  • Une fois dans le Lobby, nous sollicitons toutes les Salles qui se créent dans la région, puis nous pouvons soit rejoindre l'une des Salles, soit créer notre propre Salle.
  • Après avoir rejoint la salle, nous demandons une liste des joueurs connectés à la salle et instancions leurs instances Player, qui sont ensuite synchronisées avec leurs instances locales via PhotonView.
  • Lorsque quelqu'un quitte la salle, son instance est détruite et il est retiré de la liste des joueurs.

1. Mise en place d'un lobby

Commençons par créer un MainMenu qui contiendra une logique de Lobby (Parcourir les salons existants, créer de nouveaux salons, etc.).

  • Créez une nouvelle scène et appelez-la "MainMenu"
  • Créez un nouveau script C# et appelez-le GameLobby
  • Dans la scène MainMenu, créez un nouveau GameObject. Appelez-le "_GameLobby" et attachez-y le script GameLobby

Ouvrez maintenant le script GameLobby.

Commençons par créer toutes les variables nécessaires:

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

La prochaine chose que nous devons faire est d'activer la connexion automatique au lobby et les statistiques du lobby, cela nous permettra de recevoir la liste des salles. Ceci est fait dans le vide Start().

De plus, nous activons automatiquementSyncScene afin que la scène soit automatiquement synchronisée une fois que nous rejoignons la salle.

Et enfin, nous appelons PhotonNetwork.ConnectUsingSettings pour nous connecter.

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

Pour savoir si une connexion à Photon Cloud a réussi, nous devons implémenter ces 2 rappels: OnReceivedRoomListUpdate() et OnFailedToConnectToPhoton(object parameters).

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

Vient ensuite la partie UI, où la navigation dans la salle et la création de la salle sont effectuées:

Lobby du Réseau Photon

Et enfin, nous implémentons 4 autres rappels: OnPhotonCreateRoomFailed(), OnPhotonJoinRoomFailed(object[] cause), OnCreatedRoom() et OnJoinedRoom().

Ces rappels sont utilisés pour déterminer si nous avons rejoint/créé la salle ou s'il y a eu des problèmes lors de la connexion.

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

Et voici le dernier script 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. Création d'un préfabriqué Player

Dans les jeux multijoueurs, l'instance Player a 2 faces: Local et Remote.

Une instance locale est contrôlée localement (par nous).

L'instance distante, en revanche, est une représentation locale de ce que fait l'autre joueur. Il ne devrait pas être affecté par notre entrée.

Pour déterminer si l'instance est locale ou distante, nous utilisons un composant PhotonView.

PhotonView agit comme un messager qui reçoit et envoie les valeurs qui doivent être synchronisées, par exemple, la position et la rotation.

Commençons donc par créer l'instance de joueur (si vous avez déjà votre instance de joueur prête, vous pouvez ignorer cette étape).

Dans mon cas, l'instance du joueur sera un simple cube déplacé avec les touches W et S et tourné avec les touches A et D.

Instance de lecteur réseau Photon

Et voici un simple script de contrôleur:

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

L'étape suivante consiste à ajouter un composant PhotonView.

  • Ajouter un composant PhotonView à Player Instance
  • Créez un nouveau script C#, appelez-le PlayerNetworkSync et ouvrez-le (ce script sera utilisé pour communiquer via PhotonView)

La première chose que nous devons faire est de remplacer MonoBehaviour par Photon.MonoBehaviour. Cette étape est nécessaire pour pouvoir utiliser la variable photonView mise en cache au lieu d'utiliser GetComponent<PhotonView>().

public class PlayerNetworkSync : Photon.MonoBehaviour

Après cela, nous pouvons passer à la création de toutes les variables nécessaires:

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

Ensuite, dans le vide Start(), nous vérifions si le lecteur est local ou distant en utilisant 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);
            }
        }
    }

La synchronisation proprement dite est effectuée via le rappel de PhotonView: 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();
        }
    }

Dans ce cas, nous n'envoyons que la position et la rotation du joueur, mais vous pouvez utiliser l'exemple ci-dessus pour envoyer toute valeur qui doit être synchronisée sur le réseau, à une fréquence élevée.

Les valeurs reçues sont ensuite appliquées dans le 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);
        }
    }

Voici le script 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);
        }
    }
}
  • Ajoutez le script PlayerNetworkSync.cs à PlayerInstance et attribuez-le aux composants observés PhotonView.
  • Affectez le PlayerCntroller.cs au "Local Scripts" et affectez les GameObjects (que vous souhaitez désactiver pour les joueurs distants) au "Local Objects"

  • Enregistrez PlayerInstance dans Prefab et déplacez-le dans le dossier appelé Resources (s'il n'y a pas de dossier de ce type, créez-en un). Cette étape est nécessaire pour pouvoir générer des objets multijoueurs sur le réseau.

3. Création d'un niveau de jeu

GameLevel est une scène qui est chargée après avoir rejoint la salle et c'est là que toute l'action se produit.

  • Créez une nouvelle scène et appelez-la "GameLevel" (Ou si vous voulez garder un nom différent, assurez-vous de changer le nom dans cette ligne PhotonNetwork.LoadLevel("GameLevel"); sur GameLobby.cs).

Dans mon cas, je vais utiliser une scène simple avec un avion:

  • Créez maintenant un nouveau script et appelez-le RoomController. Ce script gérera la logique à l'intérieur de la salle (comme faire apparaître les joueurs, afficher la liste des joueurs, etc.).

Commençons par définir les variables nécessaires:

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

Pour instancier le préfabriqué Player, nous utilisons 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);
    }

Et une interface utilisateur simple avec un bouton "Leave Room" et quelques éléments supplémentaires tels que le nom de la salle et la liste des joueurs connectés:

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

Et enfin, nous implémentons un autre callback PhotonNetwork appelé OnLeftRoom() qui est appelé lorsque nous quittons la Room:

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

Et voici le script 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");
    }
}
  • Enfin, créez un nouveau GameObject dans la scène GameLevel et appelez-le "_RoomController"
  • Attachez le script RoomController à l'objet _RoomController
  • Attribuez-lui le préfabriqué PlayerInstance et une transformation SpawnPoint, puis enregistrez la scène
  • Ajoutez à la fois MainMenu et GameLevel aux paramètres de construction.

4. Réalisation d'un build de test

Il est maintenant temps de créer une version et de la tester:

Sharp Coder Lecteur vidéo

Tout fonctionne comme prévu !

Prime

RPC

Dans Photon Network, RPC signifie Remote Procedure Call, il est utilisé pour appeler une fonction sur des clients distants qui se trouvent dans la même pièce (vous pouvez en savoir plus ici).

Les RPC ont de nombreuses utilisations, par exemple, disons que vous devez envoyer un message de chat à tous les joueurs de la salle. Avec les RPC, c'est facile à faire.

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

Remarquez le [PunRPC] avant la fonction. Cet attribut est nécessaire si vous envisagez d'appeler la fonction via des RPC.

Pour appeler les fonctions marquées comme RPC, vous avez besoin d'un PhotonView. Exemple d'appel:

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

Conseil de pro: Si votre script est un Photon.MonoBehaviour ou Photon.PunBehaviour, vous pouvez utiliser: this.photonView.RPC().

Propriétés personnalisées

Dans Photon Network, les propriétés personnalisées sont une table de hachage qui peut être attribuée au lecteur ou à la salle.

Ceci est utile lorsque vous devez définir des données persistantes qui n'ont pas besoin d'être modifiées fréquemment (par exemple, le nom de l'équipe du joueur, le mode de jeu en salle, etc.).

Tout d'abord, vous devez définir une Hashtable, ce qui se fait en ajoutant la ligne ci-dessous au début du script:

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

L'exemple ci-dessous définit les propriétés Room appelées "GameMode" et "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"]);

Les propriétés du lecteur sont définies de la même manière:

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

Pour supprimer une propriété spécifique, définissez simplement sa valeur sur null.

        //Remove property called "PlayerHP" from Player properties
        Hashtable setPlayerProperties = new Hashtable();
        setPlayerProperties.Add("PlayerHP", null);
        PhotonNetwork.player.SetCustomProperties(setPlayerProperties);
Articles suggérés
Créez un jeu de voiture multijoueur avec PUN 2
Unity ajoute un chat multijoueur aux salles PUN 2
Synchroniser les corps rigides sur le réseau à l'aide de PUN 2
Créez un jeu multijoueur dans Unity en utilisant PUN 2
Créer des jeux multijoueurs en réseau dans Unity
Compression de données multijoueur et manipulation de bits
Tutoriel de classement en ligne Unity