Photon Unity Networking基础教程 1 Lobby

连接服务器,房间访问和创建

我们首先来看这篇教程的核心,连接Photon Cloud服务器和加入房间,或者需要的话创建一个。

  1. 创建一个新的场景,保存为Launcher.unity
  2. 创建新的C#脚本Launcher
  3. 创建新的GameObject,命名为Launcher
  4. 把C#脚本添加到Launcher对象上
  5. 按照下面的内容编辑C#脚本
  6. 记得保存
using UnityEngine;

namespace Com.MyCompany.MyGame
{
    public class Launcher : MonoBehaviour
    {
        #region Public Variables
 
 
        #endregion
 
 
        #region Private Variables
 
 
        /// 
        /// This client's version number. Users are separated from each other by gameversion (which allows you to make breaking changes).
        /// 
        string _gameVersion = "1";
 
 
        #endregion
 
 
        #region MonoBehaviour CallBacks
 
 
        /// 
        /// MonoBehaviour method called on GameObject by Unity during early initialization phase.
        /// 
        void Awake()
        {
 
 
            // #NotImportant
            // Force Full LogLevel
            PhotonNetwork.logLevel = PhotonLogLevel.Full;
 
 
            // #Critical
            // we don't join the lobby. There is no need to join a lobby to get the list of rooms.
            PhotonNetwork.autoJoinLobby = false;
 
 
            // #Critical
            // 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;
        }
 
 
        /// 
        /// MonoBehaviour method called on GameObject by Unity during initialization phase.
        /// 
        void Start()
        {
            Connect();
        }
 
 
        #endregion
 
 
        #region Public Methods
 
 
        /// 
        /// Start the connection process. 
        /// - If already connected, we attempt joining a random room
        /// - if not yet connected, Connect this application instance to Photon Cloud Network
        /// 
        public void Connect()
        {
 
 
            // we check if we are connected or not, we join if we are , else we initiate the connection to the server.
            if (PhotonNetwork.connected)
            {
                // #Critical we need at this point to attempt joining a Random Room. If it fails, we'll get notified in OnPhotonRandomJoinFailed() and we'll create one.
                PhotonNetwork.JoinRandomRoom();
            }else{
                // #Critical, we must first and foremost connect to Photon Online Server.
                PhotonNetwork.ConnectUsingSettings(_gameVersion);
            }
        }
 
 
    #endregion
 
 
    }
}

让我们看看代码中都做了什么,先从Unity内容开始,然后再看PUN的内容。

  • Namespace

    虽然不是强制性的,为脚本提供适当的命名空间可防止与其他Assets和开发人员发生冲突。 如果另一个开发者创建一个类Launcher怎么办? Unity编译器会报错,你们必须重命名这个的类。 如果冲突来自您从资源商店下载的Assets,这可能很棘手。 现在,Launcher类实际上是在Com.MyCompany.MyGame.launcher这个命名空间下,别人不太可能使用与我们这个完全相同的命名空间,因为你拥有这个域名,所以使用域名逆序作为命名空间,可以使您的工作安全,组织良好。 Com.MyCompany.MyGame应该被替换为你自己的逆序域名和游戏名称,应该遵从这个良好的约定。

  • MonoBehaviour类

    注意,我们使用MonoBehaviour派生类,它可以将我们的类转换为Unity组件,然后可以放到GameObject或Prefab上。 扩展MonoBehaviour的类可以访问许多非常重要的方法和属性。 在这里,我们将使用两个回调方法,Awake()和Start()。

  • PhotonNetwork.logLevel

    在开发过程中,特别是如果这是你第一次使用PUN时,我们将要求PUN在Unity控制台上尽可能多地记录日志,以便我们准确地知道发生了什么。 您将更加自信,并且当事情按预期工作时,将此LogLevel切换到Informational。

  • PhotonNetwork.autoJoinLobby

    在Awake()期间,我们将PhotonNetwork.autoJoinLobby设置为false,因为我们不需要大厅功能,我们只需要获取现有房间的列表。 强制设置通常是一个好主意,因为在同一个项目中,你可能有另一个场景,实际上想要自动加入大厅,所以在同一个项目内,在不同的方法中间切换的话,这两个情况下都会没有问题。

  • PhotonNetwork.ConnectUsingSettings()

    在Start()期间,使用我们的公共函数connect()连接到PUN ,调用了PhotonNetwork.ConnectUsingSettings()。 注意_gameVersion变量表示你的游戏版本。 您应该将其保留为“1”,直到您需要对已经处于活动状态的项目进行大的修改。 这里要记住的重要信息是,PhotonNetwork.ConnectUsingSettings()是您的游戏的联网和连接到Photon Cloud的起点。

  • PhotonNetwork.automaticallySyncScene

    我们的游戏将有一个基于玩家数量可调整的竞技场,并确保加载的场景对每个连接的玩家是相同的,我们将利用Photon提供的非常方便的功能:PhotonNetwork.automaticallySyncScene。当该变量设置为true的时候,MasterClient可以调用PhotonNetwork.LoadLevel(),此时所有连接的玩家都会自动的加载同样的Level。

到这里,您可以保存启动场景并点击播放。 你应该在Unity控制台中看到好多条日志。特别是“已连接到masterserver”这条日志,表明我们现在已经连接并准备好加入一个房间。

编码时的良好习惯是总是测试失败的可能性。 这里我们假定计算机已连接到互联网,但如果计算机未连接到互联网会发生什么呢?让我们来看看。 关闭计算机的网络并启动场景。 你应该看到在Unity控制台错误“Connect() to 'ns.exitgames.com' failed:System.Net.Sockets.SocketException:No such host is known”。

理想情况下,我们的脚本应该知道这个问题,并对这些情况作出反应。并且无论什么情况或问题可能出现,都要能够积极响应。

我们现在处理这两种情况,并通知我们的Launcher脚本,我们到底有没有连接上PUN服务器。 这将是对PUN Callbacks的完美介绍。

PUN CallBacks

PUN的回调非常灵活,并提供了三种非常不同的实现。 让我们学习所有的三种方法,然后根据情况选择使用最适合的一个。

"magic" methods

当使用常规的MonoBehaviour的时候,可以简单创建一个私有方法:

void OnConnectedToMaster()
{
 
    Debug.Log("DemoAnimator/Launcher: OnConnectedToMaster() was called by PUN");
 
}

这挺神奇的,因为任何MonoBehaviour可以实现该方法或任何其他消息从PUN。 它遵循与Unity发送给MonoBehaviours(如Awake()或Start())主要方法相同的原则。 但是我们不会使用这个,因为如果你拼错这些“Magic”的方法,不会通知你出了错误,所以这是一个非常快速和实际的实现,但只有当知道确切的每个方法的名称,并且你非常熟悉,非常在行调试技术,才能快速找到这些类型的问题。

使用IPunCallbacks和IPunObservable接口

PUN提供了两个C#接口,IPunCallbacks和IPunObservable,你可以在类中实现。

Photon Unity Networking基础教程 1 Lobby_第1张图片
MonoDevelop: Implement Interface Methods

这是一个非常安全的方法,以确保一个类符合所有的接口,但强制开发人员实现所有的接口声明。 最好的脚本编辑器将使这个任务非常容易,如上面使用MonoDevelop时所示。 然而,脚本可能最终有很多不做任何事情的方法,但是为了编译器通过必须都实现。 所以你的脚本可以大量使用所有或大多数Pun特性。

后面的教程中,做数据序列化的时候还会使用到IPunObservable。

使用Photon.PunBehaviour

上一个部分,是我们将经常使用的技术,是最方便的一个。 我们还可以从Photon.PunBehaviour继承类,而不是创建一个从MonoBehaviour派生的类,因为它暴露了特定的属性和虚拟方法,供我们在方便时使用和覆盖。 这点非常实用,因为我们可以确定我们没有任何打字错误,我们不需要实现所有的方法。

Photon Unity Networking基础教程 1 Lobby_第2张图片
MonoDevelop: Override Method

注意:当重写方法时,大多数脚本编辑器将默认实现一个基类调用并自动填充,但在我们的例子中不需要,因此作为Photon.PunBehaviour的一般规则,不会调用基类方法。

注意:当重写方法时,另一个很大的好处是,您通过简单地悬停在方法名称上从帮助中获益。

好的,让我们实现以下OnConnectedToMaster()和OnDisconnectedFromPhoton()这两个PUN回调。

  1. 编辑Launcher脚本

  2. 把基类改成Photon.PunBehaviour

    public class Launcher : Photon.PunBehaviour {

  3. 在类的末尾添加下面两个方法,为了清晰请写到这个区块Photon.PunBehaviour CallBacks里面

     #region Photon.PunBehaviour CallBacks 
     public override void OnConnectedToMaster()
     {
     Debug.Log("DemoAnimator/Launcher: OnConnectedToMaster() was called by PUN");          
     } 
     public override void OnDisconnectedFromPhoton()
     { 
     Debug.LogWarning("DemoAnimator/Launcher: OnDisconnectedFromPhoton() was called by PUN");        
     }    
     #endregion
    
  4. 保存脚本

现在,如果我们在有或没有互联网的情况下启动这个场景,我们可以采取适当的步骤通知玩家是否进行下一步。我们将在下一节中讨论构建UI。现在我们将处理成功的连接:

因此,我们在OnConnectedToMaster()方法中追加以下调用:

// #Critical: The first we try to do is to join a potential existing room. If there is, good, else, we'll be called back with OnPhotonRandomJoinFailed()  
PhotonNetwork.JoinRandomRoom();

正如注释所说,我们需要被告知尝试加入一个随机房间是否失败,在这种情况下,我们需要实际创建一个房间,所以我们在我们的脚本中实现OnPhotonRandomJoinFailed这个PUN回调。创建一个房间使用PhotonNetwork.CreateRoom(),你已经猜到,当我们成功地加入一个房间时使用PUN回调OnJoinedRoom()。

public override void OnPhotonRandomJoinFailed (object[] codeAndMsg)
{
    Debug.Log("DemoAnimator/Launcher:OnPhotonRandomJoinFailed() was called by PUN. No random room available, so we create one.\nCalling: PhotonNetwork.CreateRoom(null, new RoomOptions() {maxPlayers = 4}, null);");
 
    // #Critical: we failed to join a random room, maybe none exists or they are all full. No worries, we create a new room.
    PhotonNetwork.CreateRoom(null, new RoomOptions() { maxPlayers = 4 }, null);
}
 
public override void OnJoinedRoom()
{
    Debug.Log("DemoAnimator/Launcher: OnJoinedRoom() called by PUN. Now this client is in a room.");
}

现在如果你运行场景,并且你应该遵循连接到PUN连续的逻辑,尝试加入现有房间,否则创建房间并加入新创建的房间。

到这里,尽管我们现在已经介绍了连接和加入一个房间的关键方面,但是有一些事情不是很方便,迟早药解决它们。 这些不是真正与学习PUN有关,但从总体角度来说很重要。

在Unity Inspector中暴露变量

MonoBehaviours会自动将他们的公共属性暴露给Unity Inspector。这是Unity中一个非常重要的概念,在我们的例子中,我们将修改我们定义LogLevel的方式,并创建一个公共变量,以便我们可以在不触及代码本身的情况下进行设置。

/// 
/// The PUN loglevel. 
/// 
public PhotonLogLevel Loglevel = PhotonLogLevel.Informational;

以及修改Awake():

// #NotImportant
// Force LogLevel
PhotonNetwork.logLevel = Loglevel;

所以,现在我们不强制脚本是一个特定类型的LogLevel,我们只需要在Unity Inspector中设置它,然后点击运行,不需要打开脚本,编辑它,保存它,等待Unity重新编译并最终运行。 这种方式更有效率和灵活性。

我们也会这样做,每个房间的玩家数量最多。 在代码中硬编码不是最好的做法,而是让它作为一个公共变量,以便我们以后可以确定和调整这个数字,而不需要重新编译。

在类声明的开头,Public Variables代码段中加入:

/// 
/// The maximum number of players per room. When a room is full, it can't be joined by new players, and so new room will be created.
///    
[Tooltip("The maximum number of players per room. When a room is full, it can't be joined by new players, and so new room will be created")]
public byte MaxPlayersPerRoom = 4;

然后修改PhotonNetwork.CreateRoom()调用的地方来使用这个公共变量。

// #Critical: we failed to join a random room, maybe none exists or they are all full. No worries, we create a new room.
PhotonNetwork.CreateRoom(null, new RoomOptions() { maxPlayers = MaxPlayersPerRoom }, null);

在Unity Inspector中效果如下:

Photon Unity Networking基础教程 1 Lobby_第3张图片
Launcher Script Inspector

原文地址:http://doc.photonengine.com/en-us/pun/current/tutorials/pun-basics-tutorial/lobby#photon-cloud

你可能感兴趣的:(Photon Unity Networking基础教程 1 Lobby)