Multijugador con Photon

Contactar con el profesor

Vamos a utilizar los servidores de Photon para hacer un juego multijugador. Estos servidores tienen instalada una aplicación llamada PhotonServer. Nosotros también podríamos instalar PhotonServer en nuestro propio servidor, pero utilizando los servidores de Photon nos ahorramos este paso. Los servidores de Photon reciben el nombre de Photon Cloud

PUN (Photon Unity NetWorking) es un framework que tiene scripts que nos facilitan programar videojuegos multiplayer. PUN es:

  • gratuito hasta los 20 UCC (Usuarios Conectados Simultáneamente). Si sobrepasas el límite, los nuevos usuarios no se podrán conectar.
  • Hay un límite de 500 mensajes por Room (partida).

Conexión y Join una Room

  1. Registramos una cuenta en https://www.photonengine.com/
  2. Tras loguearnos creamos una nueva aplicación cuyo Photon Type será Photon PUN.
  3. Copiamos el App ID de la aplicación.
  4. Vamos a Unity 3D e instalamos Photon Networking 2 Free. Al termino de la instalación nos pide un código. Pegamos el código de antes.
  5. Creamos un Empty al que vinculamos el siguiente código:
    1. Cuando pulsamos el botón de Connect, llamamos a la función Connect()
    2. Cuando nos hemos conectado, se ejecuta automáticamente el método OnConnectedToMaster(). Este método habilitará el botón Join Random
    3. Cuando pulsamos el botón de Join Random, llamamos a la función JoinRandom()
    4. Cuando nos hemos unido a una room, se ejecuta automáticamente el método OnJoinedRoom()(). Dentro del FixedUpdate, evaluamos constantemente si nos hemos unido a una Room.Este método habilitará el botón Join Random
using System.Collections;
using System.Collections.Generic;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.UI;
namespace Photon.Pun.Demo.PunBasics{
	public class AutoLobby : MonoBehaviourPunCallbacks{
		public Text Log;
		public Text PlayerCount;
		public int playersCount;

		public byte maxPlayersPerRoom = 4;
		public byte minPlayersPerRoom = 2;
		private string roomName = "amor";
		public Button buttonJoinRoom;
		public Button buttonLoadArena;
		public Text nombre;

		void Start(){
			// La IP del servidor al que se conectará el player será almacenada en las PlayerPrefs.
			// Debemos resetear las PlayerPrefs para evitar ciertos problemas de conexión
			PlayerPrefs.DeleteAll();
			ConnectToPhoton();
		}

		void Awake(){
			// La siguiente línea nos permite sincronizar la escena para todos los players de la room
			PhotonNetwork.AutomaticallySyncScene = true;
		}

		void ConnectToPhoton(){
			Log.text = "Connecting...";
			PhotonNetwork.GameVersion = ""+1; //1
			if (PhotonNetwork.ConnectUsingSettings()){
				Log.text += "\n Connected to server";
			}else{
				Log.text += "\n Falling Connecting to Server";
			}
		}

		// Photon Methods
		public override void OnConnected(){
			base.OnConnected();
			Log.text += "\nConnected to Photon!";

			buttonJoinRoom.interactable = true;
			buttonLoadArena.interactable = false;
		}

		public void JoinRoom(){
			Log.text += "\nJoinRoom() method";

			if (PhotonNetwork.IsConnected){
				PhotonNetwork.LocalPlayer.NickName = nombre.GetComponent<Text>().text; //1
				Log.text += "\nPhotonNetwork.IsConnected! | Trying to Create/Join Room ";
				RoomOptions roomOptions = new RoomOptions(); //2
				TypedLobby typedLobby = new TypedLobby(roomName, LobbyType.Default); //3
				PhotonNetwork.JoinOrCreateRoom(roomName, roomOptions, typedLobby); //4

				Log.text +="\nFin JoinRoom(): " + PhotonNetwork.LocalPlayer.NickName;
			}
		}

		public override void OnJoinedRoom(){
			if (PhotonNetwork.IsMasterClient){
				buttonJoinRoom.interactable = false;
				buttonLoadArena.interactable = true;
				Log.text += "\nYour are Lobby Leader";
			}else{
				Log.text += "\nConnected to Lobby";
			}
		}

		public void LoadArena(){
			if (PhotonNetwork.CurrentRoom.PlayerCount > 1){
				PhotonNetwork.LoadLevel("juego");
			}else{
				Log.text += "\nMinimum 2 Players required to Load Arena!";
			}
		}

		void Update(){
			if (PhotonNetwork.InRoom){
				playersCount = PhotonNetwork.CurrentRoom.PlayerCount;
				PlayerCount.text = playersCount + "/" + maxPlayersPerRoom;
			}
		}
        
		public override void OnJoinRandomFailed(short returnCode, string message){
			Log.text += "\nNo Rooms to Join, creating one...";
			if (PhotonNetwork.CreateRoom(null, new Photon.Realtime.RoomOptions() { MaxPlayers = maxPlayersPerRoom })){
				Log.text += "\n Room Created";
			}else{
				Log.text += "\nFail Creating Room";
			}
		}
	}
}
multijugador con photon

Cargamos la escena de juego

1. AutoLobby.cs
...

private void LoadMap(){
	PhotonNetwork.LoadLevel("juego");
}

2. GameController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using UnityEngine.UI;
namespace Photon.Pun.Demo.PunBasics{ 
	public class GameController : MonoBehaviourPunCallbacks{
		private GameObject player1;
		private GameObject player2;
		public Transform player1Position;
		public Transform player2Position;

		void Start(){
			if (PlayerManager.LocalPlayerInstance == null){
				if (PhotonNetwork.IsMasterClient){
					player1 = PhotonNetwork.Instantiate("PlayerMonteserin", player1Position.transform.position, player1Position.transform.rotation, 0);
				}else{
					player2 = PhotonNetwork.Instantiate("PlayerMonteserin", player2Position.transform.position, player2Position.transform.rotation, 0);
				}
			}
		}
	}
}

3. Creamos un Prefab de nuestro player.

Importaremos Joystick Pack de la Asset Store de Unity. En la ruta Joystick Pack/Prefabs usaremos el Prefab Floating Joystick que debemos añadir a un canvas.

joystick pack

Utilizaremos el siguiente código para gestionar su movimiento. El prefab del Player tendrá un cubo de tal forma que cuando lo pulsemos subirá para arriba:

PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using Photon.Pun;
using UnityEngine;

public class PlayerController : Photon.Pun.MonoBehaviourPun{
    public bool isMovingUp, isMovingDown = false;
    Rigidbody rb;
    private Vector2 movement;

    public Joystick joystick;
    PhotonView photonView;

    void Start(){
        photonView = gameObject.GetComponent<PhotonView>();
        rb = GetComponent<Rigidbody>();
        joystick = GameObject.Find("Canvas").transform.Find("Floating Joystick").GetComponent<FloatingJoystick>();
    }

    void FixedUpdate(){
        if (photonView.IsMine){
            this.movement = this.rb.velocity;
            if (joystick.Horizontal > 0)this.movement.x = 2;
            else if (joystick.Horizontal < 0) this.movement.x = -2;
            else this.movement.x = 0;

            if (joystick.Vertical > 0) this.movement.y = 2;
            else if (joystick.Vertical < 0) this.movement.y = -2;
            else this.movement.y = 0;
            rb.velocity = movement;
        }
    }
}
  1. Añadimos al GameObject del Prefab los siguientes scripts:
    • PhotonView ubicado en /Assets/Photon/PhotonUnityNetworking/Code/
    • PhotonTransformView ubicado en /Assets/Photon/PhotonUnityNetworking/Code/
  2. Arrastramos el componente PhotonTransformView al campo Observed ComponentsTransformView.
  3. Debemos asegurarnos de que el TransformView tiene la opción Observe option con el valor Unreliable On Change
    Multijugador con Photon 1
  4. En este momento, si compilamos el juego y lo ejecutamos dos veces, veremos que al mover el personaje en una de las dos instancias de juego, este se mueve en la otra instancia de juego. Es mejor que probemos el juego en dispositivos independientes. Arrancando dos instancias del juego en el mismo dispositivo, la sincronización era bastante mala.
← Importar personaje 3D a la escena
Recuperar un array de objetos del mismo tipo →

Aviso Legal | Política de privacidad