阿星的Unity教學部落格

預計會走向 日文Unity部落格翻譯、Photon研究、Unity小工具、Unity編輯器開發、框架研究

【Unity】我也想使用Photon #01 多種連線方式介紹

原文為此部落格文章,以下內容皆從日文翻譯過來。
內容大部分是うら干物書き 自身使用後的心得文章。 
前面有標[阿星Tip]就是翻譯者阿星自己測試或者心得。

www.urablog.xyz

我也想做看看多人連線的遊戲ㄚㄚㄚㄚ…..突然這樣覺得

也因為 Unityまとめ 這個網站提供的資訊,偶爾不經意會看到Photon教學的部落格文章。

以前常常聽到在Unity內使用Photon,很簡單就可以製作多人遊戲,但始終沒有真正嘗試去使用Photon。

難得的機會、不使用Photon去製作遊戲看看嗎?

但這系列可能是很常見的Photon內容介紹的部落格。(謙虛的意思 ww)


本篇文章是使用Unity5.4.1f1以及PUN1.75。

PUN

Unity使用的Photon的Asset名稱為 Photon Unity Networking,簡略來說就是PUN

這要怎麼念比較好呢?
P-U-N嗎?  還是PUN(與同音)呢?
只講PUN(胖)的話似乎有點讓人搞混
以前參加分享會的時候,被人這樣問:「怎沒用PUN做遊戲看看?」,
以為是在問我說使用"麵包"或者"熱狗麵包"之類做遊戲。
[阿星Tip]:PUN (胖) 在日文是麵包的意思,會台語的人應該也知道麵包在台語 念作 胖。
最初音響上面的聲道的專有名詞也念作胖,聽到的時候會稍微小混亂一下呢。
以上為題外話。

[阿星Tip]:另外Photon正確唸法應該是 佛燙 而非 佛ㄊㄥˇ

Asset導入並啟用

從AssetStore中下載PUN插件,並導入到專案資料夾內。
https://www.assetstore.unity3d.com/en/#!/content/1786

導入以後,會跑出一個視窗。
似乎有重要的東西要讓我們設定,但我有點懶,屬於先跳過之後再設定的那種人。

f:id:starlove124760:20171018020302p:plain

之後就從什麼都沒有的空場景開始試試看。
結果就又跳出警告視窗。

f:id:starlove124760:20171018020334p:plain

這個設定的部分就從前面提到的Unityまとめ網站中,透過學習前人的文章資訊開始使用Photon吧。
從前輩們的文章中得到的資訊真是幫了大忙,我參考了以下的網頁。

tech.pjin.jp

sleepnel.hatenablog.com

從Photon官方網站,登入帳號後取得應用程式頁面中的AppID,將會使用這個AppID來設定我們的專案。
[阿星Tip]:如果有註冊或者取得ID的問題可以參考 Photon Taiwan – Medium

medium.com

似乎有串起來的感覺。只是…

有個必需要做的步驟,就是將剛剛得到的AppID設定給一個叫做 PhotonServerSettings 的檔案。
該檔案位於Photon Unity Networking/Resources 資料夾內的PhotonServerSettings 檔案。
也可以直接從Project View (資料夾視窗)中找尋,但其實剛剛導入Photon的時候就有跳出一個設定的視窗了(也就是剛剛偷懶跳過那邊)。
從Unity編輯器上方的Windows > Photon Unity Networking > PUN Wizard可以打開此設定視窗。
快捷鍵為「Alt + P
選取視窗中的 Loacte PhotonServerSettings,就會看到 PhotonServerSettings 的檔案在Inspector視窗中顯示。

f:id:starlove124760:20171018020801p:plain

從前輩們的文章中,Hosting設定上選擇PhotonCloud,並在AppID的框框輸入AppID
並勾選 Auto - Join Lobby 的框框,再來只要使用 PhotonNetwork.ConnectUsingSettings() 這個API就OK了。

f:id:starlove124760:20171023041326p:plain

using UnityEngine;

public class DemoNetwork : MonoBehaviour
{
    void Start()
    {
        PhotonNetwork.ConnectUsingSettings( null );
    }

    void OnJoinedLobby()
    {
        Debug.Log( "OnJoinedLobby()" );
    }

} // class DemoNetwork

OnJoinedLobby()內有寫一個Debug.Log。

    看起來這樣就能用Photon連線到大廳了,但是有幾個在意的點。

    像是PhotonServerSettings 的檔案中有一個Hosting選項有很多可以選擇,但到底具體是什麼功用呢?

    除此之外,使用 PhotonNetwork.ConnectUsingSettings()的時候、也發現有其他的Connect API的存在…。

f:id:starlove124760:20171018022315p:plain

那麼就稍微看一下這些API吧。

有很多的Connect()相關函數

讓我們看一下PhotonNetwork的類別內容吧~ 

https://doc-api.photonengine.com/en/pun/current/class_photon_network.html

有好多Connect() 功能相關的函數呢!

  • ConnectUsingSettings()
  • ConnectToMaster()
  • ConnectToBestCloudServer()
  • ConnectToRegion()

不知不覺了解到ConnectUsingSettings()這個API是從PhotonServerSettings 檔案內
拿取相關資訊來使用、但其他的函數現階段就不太清楚了。

讓我們看一下 PhotonServerSettingsHosting 中的選項有哪些種類吧。

  • NotSet
  • PhotonCloud
  • SelfHosted
  • OfflineMode
  • BestRegion

似乎有很多是跟Connect API相關的參數呢

ConnectToMaster() 與 SelfHosted

    就從最容易理解的 ConnectToMaster()APISelfHosted 開始看吧。

 bool ConnectToMaster( string masterServerAddress, int port, string appID, string gameVersion )

masterServerAddress //Server的IP位址
port //Server連接使用的Port
appID //Application ID
gameVersion //這一個版本的編號

    似乎是自己架設PhotonServer的情形使用的API
    順帶一提gameVersion 是可以填入任意文字的、這個gameVersion文字使用時也可以將玩家做區分。
    像是輸出後的執行檔中設定ver1.0跟ver1.1是可以一起進行遊戲的沒錯、但如果是設定成ver2.0的話就可讓不同版本的玩家無法一起連線、可以更改這個數值的樣子。
    還嘗試了一下、跟Invoke()使用的時候不同、gameVersion 即使指定了null也不會讓編輯器Crash的樣子。

[阿星Tip]:測試後Invoke填null、Unity2017不會Crash。
    接著看一下Hosting選項中的SelfHosted設定畫面。
 

f:id:starlove124760:20171022011325p:plain

可設定的參數如下、

  • Server Address
  • Server Port
  • Protocol
  • AppId

和 ConnectToMaster()API填入的參數相同、但SelfHosted設定是為了給ConnectUsingSettings()使用的。

[阿星Tip]:因ConnectUsingSettings不用給相關連線參數,所以這邊ConnectUsingSettingsAPI是直接吃這個SelfHosted底下的參數設定來執行的

進入腳本中確認ConnectUsingSettings()API一下、看了實際Photon呼叫情況、果然是直接使用這底下的參數沒錯。

[阿星Tip]:PhotonServerSettings檔案中的選項參數。
 ConnectToMaster()API雖然無法直接指定Protocol、當想在自己寫的程式內指定所連線的Protocol的時候、同樣是呼叫PhotonNetwork類別中的SwitchToProtocol()API去指定。

這次有點可惜的地方在於沒有使用自己架設Server的連線方式去連線。

ConnectToBestCloudServer() 與 BestRegion

接著要看的是、ConnectToBestCloudServer()BestRegion。
這個也是與ConnectToMaster()類似名字的API、所以在設定上推測應該一樣。

Hosting選項中的BestRegion設定畫面。

f:id:starlove124760:20171022014017p:plain

    可以被設定的參數如下。

  • Enabled Regions
  • AppId
  • Protocol

BestRegionEnabled Regions參數是可以從被指定的地區中、選擇連線最好的地區去做連線的方式。

    那麼ConnectToBestCloudServer()該指定甚麼參數給它呢?
    感覺大概是跟BestRegion一樣的參數吧……

 bool ConnectToBestCloudServer ( string gameVersion )

 ( ゚д゚)ポカーン

    居然只有gameVersion一個參數阿。

    與BestRegion中可指定地區的Enabled Regions方式不同!

 那麼問題在於這個API、缺少可以指定AppID參數!
   AppID 是必須的嗎? 

 讓我們在PhotonServerSettings 中不指定AppID然後呼叫看看ConnectToBestCloudServer

f:id:starlove124760:20171023042751p:plain

f:id:starlove124760:20171022015436p:plain

Operation failed: OperationResponse 220: ReturnCode: 32767 (Empty application id). Parameters: {} Server: NameServer
The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account.

果然爆炸了阿。
被紅字告知AppID是空的,但原本在使用ConnectToBestCloudServer的時候沒有讓我們填入不是嗎。讓我們看看ConnectToBestCloudServer裡面寫了些什麼。

if (PhotonServerSettings == null)
{
    Debug.LogError("Can't connect: Loading settings failed. ServerSettings asset must be in any 'Resources' folder as: " + PhotonNetwork.serverSettingsAssetFile);
    return false;
}

if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode)
{
    return PhotonNetwork.ConnectUsingSettings(gameVersion);
}

networkingPeer.IsInitialConnect = true;
networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion);

幾乎也是從PhotonServerSettings 檔案中取得的數值…。

原來如此。這邊是我誤會了。
以為只有ConnectUsingSettings是參考 PhotonServerSettings 而已。
   但並非如此、除了ConnectToMaster()是需要 AppID的參數以外、其他的Connect API的參數都是參考PhotonServerSettings 檔案內的相關參數的。

   ConnectUsingSettings()文字中的UsingSettings的部分大概是關於參考PhotonServerSettingsHosting選項的意思。
   關於這件事情只要確認ConnectUsingSettings()API內容以後就能夠了解了。 

if (PhotonServerSettings.HostType == ServerSettings.HostingOption.SelfHosted)
{
    networkingPeer.IsUsingNameServer = false;
    networkingPeer.MasterServerAddress = (PhotonServerSettings.ServerPort == 0) ? PhotonServerSettings.ServerAddress : PhotonServerSettings.ServerAddress + ":" + PhotonServerSettings.ServerPort;

    return networkingPeer.Connect(networkingPeer.MasterServerAddress, ServerConnection.MasterServer);
}

if (PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion)
{
    return ConnectToBestCloudServer(gameVersion);
}

return networkingPeer.ConnectToRegionMaster(PhotonServerSettings.PreferredRegion);

   了解到根據 PhotonServerSettings.HostType 不同Connect API的參數也會不同。

 原來如此、PhotonServerSettings 檔案不好好設定是不行的呢
   一開始我們使用的ConnectToMaster()可以在程式中設定相關參數、就以為其他的Connect API也可以都在程式內設定相關參數。
 因為上面這些原因、所以在我們使用 ConnectToBestCloudServer() API的時候、設定BestRegion 中的參數是必要的。

ConnectToRegion() 與 PhotonCloud

 最後是這兩個。
   與ConnectUsingSettings() 中確認過的一樣、這個API會使用Hosting中填入參數。

 static bool ConnectToRegion(CloudRegionCode region, string gameVersion)

region //指定想要連接的地區
gameVersion //這一個版本的編號

f:id:urahimono:20160913075719p:plain

  • Region
  • AppId
  • Protocol

 與BestRegion 不同的是,ConnectToRegion是直接連線的類型呢。
   阿! 與 ConnectToBestCloudServer()不同、ConnectToRegion()是可以填入地區參數的API

    嗯、除了 offlineMode*1 以外、Connect相關API都講解完了呢。
    最後的結論、跟前人所得出的結論一樣、總之 呼叫 ConnectUsingSettings()就對啦。

 講了這麼長一篇、這樣的速度哪時候才能做完遊戲呢…。

下一篇

starlove.hatenablog.com

*1:提供一種不連線也能使用Photon的功能,可視作單機執行。