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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容