2016年12月14日 星期三

[Unity教學] 2D連線小遊戲製作 Part.2

這篇分為2個部分

1.網路架構基本概念
2.讓玩家登入吧

前言:
unity在5.x以後使用了的新的網路連線方法,簡稱UNet

為了解說方便,製作一個遊戲名叫 搶奪20 / Rob20 的連線小遊戲

規則:
兩個人輪流喊1~2個數字,先搶到20的人勝利

看此篇前建議先看前面的篇章喔
連線小遊戲製作part1


網路架構基本概念


1.UNet 是個以 Server 為主導的系統
2.每個物件都需要有Network Identity



白話文:

譬如說在遊戲的角色做了蹲下這個動作,就必須要告知Server,在由Server同步到其他玩家的遊戲畫面上。

Unity官方的圖
所以一個玩家操控的角色,至少會有3個"分身",一個在自己電腦上,一個在別人電腦上,一個在Server上。

所以不像單機遊戲的寫法,C#的方法(method)又分為在Server執行、在Client執行兩種。

以場景(Scene)來說,也要注意物件會根據 Server或是Client而有不同。

Network Identity又是甚麼呢,比較像是一個在網路連線功能上的一個身分證,場景中的物件要有這個元件才能正常運作~

Network Identity 有Server only與Local Player Authorit兩個選項,這是一種"權限"的概念,就是這個物件歸誰管的意思啦。

比較簡單的分法:
玩家的角色會把Local Player Authorit打勾,邏輯處理的物件會把Server only打勾

Server only打勾的話,那這個物件就只會在Server端才能看到,把Local Player Authorit打勾或是都不勾的話 Server 端與 Client 端都會有

只在Server上出現的物件,拿來做邏輯的判斷,還有處理各個玩家發送過來的訊息。

有了一些基本概念後就接著製作下去吧~


讓玩家登入吧


這個遊戲要讓兩個玩家能連線,還要在他們的畫面上顯示自己的角色圖示

這邊用兩個不同的圖案來當作角色



伺服器端

Server這邊要能夠知道玩家已連線,並告知玩家是玩家1 或是玩家2

1.首先新增一個物件,命名為GM
2.新增Network Identity,必把Server only打勾
3.新增Script命名為GM

在GM.cs先把原本的都砍掉,然後輸入這幾行

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class GM : MonoBehaviour
{
    public List<Player> allPlayer = new List<Player>();

    public void Login(Player player)
    {
        allPlayer.Add(player);
        player.RpcSetPlayer(allPlayer.Count);
    }
}

解說:
Login()是要讓玩家登入
allPlayer會記錄現在登入的玩家
第一次輸入時會有錯誤的情況,不過沒關係,馬上來製作Client端的物件

如果unity錯誤到無法繼續編輯,可以先把GM的勾勾掉


玩家端

玩家的部分用canvas做一個顯示角色的地方,每個玩家顯示的角色圖示要不一樣

1.新增一個Canvas,命名為cvsClient
2.新增Network Identity,把Local Player Authorit打勾


1.新增兩個UI > Image在 cvsClient 底下
2.調整位置
3.把 player1.png 與 player2.png  拖到對應的位置上
4.把物件本身的勾勾掉,讓圖片物件失效


1.把cvsClient拖至Project頁籤的區塊,讓它變成Prefab


1.把變成 Prefab 的 cvsClient 拖至 NetworkMsg 的 Player Prefab上,透過這個動作註冊物件,告訴 unity 這個物件代表玩家,並且在玩家連線成功時自動產生在場景上
2.刪除場景中的cvsClient
3.繼續在Prefab上的cvsClient操作


新增一個Script命名為Player,把原本的全部砍掉,然後輸入這幾行

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class Player : NetworkBehaviour
{

    public Image ImgPlayer1;
    public Image ImgPlayer2;
    GM gm;

    void Start()
    {
        if (isServer)
        {
            gm = GameObject.Find("GM").GetComponent<GM>();
            gm.Login(this);
        }
    }

    [ClientRpc]
    public void RpcSetPlayer(int id)
    {
        if (isLocalPlayer)
        {
            switch (id)
            {
                case 1:
                    ImgPlayer1.gameObject.SetActive(true);
                    break;
                case 2:
                    ImgPlayer2.gameObject.SetActive(true);
                    break;
            }
        }
    }
}


這裡會有點難懂~~請加油~

首先呢出現了第一個新的東西叫 NetworkBehaviour 而不是 MonoBehaviour,繼承它可以讓我們用一些額外的功能。

還記得之前說過的玩家角色至少會有3個"分身"嗎,當玩家連線成功時,Server會在這3個地方創建出cvsClient。

當cvsClient被創建時,第一步會先執行Start區塊內的程式,但是GM只有在Server端才有阿,所以要用isServer去判斷。

isServer 就是 NetworkBehaviour 提供的變數,它會自動判斷執行它的環境是否在Server上。

只有在 Server 端的cvsClient去進行 Login(),GM.cs 中的 Login()又呼叫了 Player.cs 中的 RpcSetPlayer(),並把玩家順位傳遞進去。

[ClientRpc]這個標籤很特別,它的功能就告訴 unity 這個方法是在Server 端被呼叫, Client 端去執行。

然後 Client 端的 Player.cs 就依據接收到的參數來顯示相對應的玩家圖示。

流程是這樣:
1.Server上的Player.cs呼叫Server上的GM.cs的Login();
2.Server上的GM.cs呼叫Server上的Player.cs 的 RpcSetPlayer()
3.Server上的Player.cs 的 RpcSetPlayer()被呼叫後實際是執行 Client上的Player.cs 的 RpcSetPlayer()

細部解說:

using UnityEngine.Networking;寫網路功能必備
NetworkBehaviour繼承MonoBehaviour,提供了 isServer、isClient等參數
[ClientRpc]這個標籤所標示的方法只會在Client端執行

編譯成exe檔執行看看


開兩個遊戲視窗,一個選Host一個選Client
可以看到Host玩家顯示的是三角形,另一個是五角形
那就表示成功囉~

這篇就到這篇結束囉~

下一篇會講按鈕功能製作和數字面板同步更新的方法

感謝各位的觀看!!

5 則留言:

  1. 作者已經移除這則留言。

    回覆刪除
    回覆
    1. 感謝你的觀看~
      如果有甚麼不了解的地方歡迎一起討論喔^^

      刪除
  2. 很感謝您的教學, 非常清楚明瞭!
    今天照做了一下, 做到 part2 結束可以執行, 連線也是成功的, 也會產生 cvsClient(clone), 唯獨player image不會顯示, 在想自己是不是什麼地方沒有注意到才有這個錯誤 ><
    另外想請問, 如果製作完多人連線的遊戲, 希望放在server上面供每次約三十人連線使用, 不知道應該放在自己的server上面好呢, 還是利用 photon cloud 這類的服務好 ?
    真的很不好意思, 新手發問, 謝謝您 !

    回覆刪除
  3. bream您好
    非常感謝您提出問題~

    首先第一個問題player image不會顯示:
    我猜想是否是被其他物件(EX:背景)擋住了呢?還是說材質本身的設定有問題呢?或許再檢查一下就可以解決囉!

    第二個問題呢:
    某燕本人沒有測試過30人左右的連線遊戲,但我的建議或許可以給你參考~
    1.考慮server的乘載能力
    伺服器是否能供30人在線上沒有問題,連線是否順暢,硬體是否夠力?
    2.自己是否有興趣維護server
    photon 很強大,但有些功能或許不是免費的(?),如果photon 完全符合您的遊戲開發需求,那恭喜你photon 是你的好選擇。那如果只是想架簡單的伺服器(EX:紀錄分數),那也可以考慮自己架,隨著功能開發慢慢學,或許能學到比較多的東西~

    希望某燕的回答可以對bream的開發過程有一點點幫助,那我就很開心了~
    最後希望有其他問題的話,也歡迎一起討論喔~

    回覆刪除
  4. 謝謝Swallow的回答~~
    在 [ClientRpc] 這裡的code加上了print(id); 來查驗是不是有執行到這邊的程式碼,但是好像沒有跑到這邊 ><
    執行中去看cvsClient(Clone)手動把ImgPlayer打勾是可以在Game View上面顯示,所以還在找尋錯誤源頭中~

    第二個問題對我很有幫助,我會先測試看看自己的Server能否乘載那麼多人的使用 :)

    謝謝您!

    回覆刪除