2016年12月16日 星期五

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

這篇會講到

1.製作開頭場景
2.連線的方式與Match Maker

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

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


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



這篇會讓這個遊戲更加的完整,我們會做一個遊戲開始畫面,並把連線的面版搬拿過去


開頭場景


首先呢我們先新增一個場景命名為title,開始拉畫面吧~~

我希望開頭畫面有一點科幻的感覺,就找了方塊的圖當作背景

在這個網站上有許多免費的自行http://www.fontspace.com/
這裡使用Digital Tech這個字型


畫面拉好了以後~
還要有Network Msg,步驟都跟之前一樣,play那個場景的Network Msg就可以刪掉囉


1.新增一個GameObject,命名為NetworkMng
2.把NetworkManagerment 和 HUD掛上去


接著把NetworkManagerment的設定完成

1.File > Buld Setting裡
2.把兩個場景加入編譯清單中
不這樣子等下會跳錯誤喔

1.再把兩個Scene拖到對應的位置,一個Online 一個Offline

unity在離線的時候切到Offline場景,連線成功時切到Onlin場景,離現場景就用title,連線場景當然用play囉

2.最後記得把cvsClient拖到Player Prefab的框框裡


接著為了要讓HUD置中在標題底下,要來新增一個script來控制

在NetworkMng下新增script,命名為SceneControl

把裡面的東西全部砍掉,新增下面的語法

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;
using System.Collections;

public class SceneControl : MonoBehaviour
{
    public NetworkManagerHUD hud;

    void Start()
    {
        hud = gameObject.GetComponent();
    }

    void Update()
    {
        if (SceneManager.GetActiveScene().name == "title")
        {
            hud.offsetX = Screen.width / 2 - 100; ;
            hud.offsetY = Screen.height - 200;
        }
        else
        {
            hud.offsetX = Screen.width - 215; ;
            hud.offsetY = -50;
        }
    }
}

原理是先抓視窗的長與寬,再計算出他的位置

場景是title的話方在畫面的中下方,場景是play的話就放在右上角


編譯成exe來測試一下吧

順便測試一下功能是不是都ok

1.連線控制面板在開頭場景時的位置
2.連線控制面板在遊戲畫面的位置
3.遊戲流程是否正確
4.輸贏判斷是否正確

如果都沒問題~那恭喜你,遊戲完成囉~(灑花

辛苦各位了,如果對這幾篇教學有甚麼問題的話,歡迎留言討論喔d(`・∀・)b

順便附上完整程式碼

GM.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class GM : MonoBehaviour
{
    public enum Round
    {
        non,
        player1,
        player2
    }

    public enum Process
    {
        start,
        waitLogin,
        decidePlayer,
        p1Action,
        p2Action,
        checkWin,
        end,
    }

    public List<Player> allPlayer = new List<Player>();
    public Round round = Round.non;
    public Process process = Process.start;
    int roundCount = -1;
    public int Mumber = 0;

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

        if (allPlayer.Count == 2)//
            process = Process.decidePlayer;//
    }

    public void AddMunber(int addMun)
    {
        Mumber += addMun;
        if (Mumber >= 20)
            process = Process.checkWin;
        else
            process = Process.decidePlayer;
    }

    void Start()
    {
        process = Process.waitLogin;
    }

    void Update()
    {
        switch (process)
        {
            case Process.waitLogin:
                foreach (Player pl in allPlayer)
                    pl.SysMsg = "等待玩家連線...";
                break;

            case Process.decidePlayer:
                roundCount++;
                if (roundCount % 2 == 0)//p1回合
                {
                    round = Round.player1;
                    process = Process.p1Action;

                }
                else//p2回合
                {
                    round = Round.player2;
                    process = Process.p2Action;
                }
                break;

            case Process.p1Action:
                allPlayer[0].SysMsg = "輪到你了!";
                allPlayer[0].SetProcess(Player.Process.action);
                allPlayer[1].SysMsg = "等待對方...";
                allPlayer[1].SetProcess(Player.Process.wait);
                break;

            case Process.p2Action:
                allPlayer[1].SysMsg = "輪到你了!";
                allPlayer[1].SetProcess(Player.Process.action);
                allPlayer[0].SysMsg = "等待對方...";
                allPlayer[0].SetProcess(Player.Process.wait);
                break;

            case Process.checkWin:
                switch (round)
                {
                    case Round.player1:
                        allPlayer[0].SysMsg = "Winner";
                        allPlayer[1].SysMsg = "Loser";
                        break;
                    case Round.player2:
                        allPlayer[1].SysMsg = "Winner";
                        allPlayer[0].SysMsg = "Loser";
                        break;
                }

                allPlayer[0].SetProcess(Player.Process.end);
                allPlayer[1].SetProcess(Player.Process.end);
                process = Process.end;
                break;
        }
    }
}


Player.cs
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class Player : NetworkBehaviour
{
    public enum Process
    {
        start,
        action,
        wait,
        end
    }

    public Image ImgPlayer1;
    public Image ImgPlayer2;
    GM gm;

    [SyncVar]
    public Process process = Process.start;

    [SyncVar]
    public string SysMsg;

    public Button btnAddOne;
    public Button btnAddTwo;
    public Text txtMunber;
    public Text txtSysMsg;

    [SyncVar]
    public int Munber;

    void Start()
    {
        if (isServer)
        {
            gm = GameObject.Find("GM").GetComponent<GM>();
            gm.Login(this);
        }
        if (isLocalPlayer)
        {
            txtSysMsg = GameObject.Find("txtSysMsg").GetComponent<Text>();
            txtMunber = GameObject.Find("txtMunber").GetComponent<Text>();
            btnAddOne = GameObject.Find("btn1").GetComponent<Button>();
            btnAddTwo = GameObject.Find("btn2").GetComponent<Button>();
            btnAddOne.onClick.AddListener(() => CmdAddMunbers(1));
            btnAddTwo.onClick.AddListener(() => CmdAddMunbers(2));
        }
    }

    void Update()
    {
        if (isServer)
            Munber = gm.Mumber;
        if (isLocalPlayer)
        {
            txtSysMsg.text = SysMsg;
            txtMunber.text = Munber.ToString();
        }
    }

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


    [Command]
    public void CmdAddMunbers(int addMun)
    {
        if (process == Process.action)
            gm.AddMunber(addMun);
    }

    public void SetProcess(Process process)
    {
        this.process = process;
    }
}



連線方式與Match Maker


基本上朋友間要互連的話,只要一方開Host另一個打IP進去就可以連線了

這裡再提供一個不使用IP就可以連線的方式

使用Unity提供的Match Maker

那麼第一步~

首先先點那個雲的按鈕


會看到Service的畫面,點multiPlayer


點Dashbord


會跳出網頁,設定玩家人數為2


儲存後回到Unity,這樣設定就ok囉


編譯成exe檔測試一下



開Server的人需要在Room Name的地方打上伺服器名稱,比如說房間1

要連的人按下Find Internet就可以在清單找到房間1

點Join Match:房間1後就連上線囉~



這篇到這裡結束了

感謝看到這裡的你

希望這系列的教學對你會有幫助

感謝大家!


沒有留言:

張貼留言