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
 
 
        /// <summary>
        /// This client's version number. Users are separated from each other by gameversion (which allows you to make breaking changes).
        /// </summary>
        string _gameVersion = "1";
 
 
        #endregion
 
 
        #region MonoBehaviour CallBacks
 
 
        /// <summary>
        /// MonoBehaviour method called on GameObject by Unity during early initialization phase.
        /// </summary>
        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;
        }
 
 
        /// <summary>
        /// MonoBehaviour method called on GameObject by Unity during initialization phase.
        /// </summary>
        void Start()
        {
            Connect();
        }
 
 
        #endregion
 
 
        #region Public Methods
 
 
        /// <summary>
        /// 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
        /// </summary>
        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,你可以在类中实现。

MonoDevelop: Implement Interface Methods

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

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

使用Photon.PunBehaviour

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

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的方式,并创建一个公共变量,以便我们可以在不触及代码本身的情况下进行设置。

/// <summary>
/// The PUN loglevel. 
/// </summary>
public PhotonLogLevel Loglevel = PhotonLogLevel.Informational;

以及修改Awake():

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

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

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

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

/// <summary>
/// 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.
/// </summary>   
[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中效果如下:

Launcher Script Inspector

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容