簡體   English   中英

Unity 中的回合制網絡

[英]Turn based networking in Unity

我想創建一個基於回合的網絡游戲,所以我必須在某個地方告訴玩家等待回合。 這看起來是一個簡單的問題,但我已經為此苦苦掙扎了很多天。 首先我用我目前的情況告訴你,如果我在任何階段做錯了什么,請告訴我。

在游戲開始之前,玩家進入大廳並可以加入游戲(或可能創建游戲)。 目前我的大廳只有 2 個按鈕,可以在其中創建服務器和檢索服務器列表。 一旦檢索到,服務器就會顯示在按鈕中。

當玩家啟動服務器時,此腳本會運行:

private void StartServer()
{
    Network.InitializeServer(2, 25000, false);
    MasterServer.RegisterHost(gameName, "Test game 2", "Welcome!");
    GameObject canvas = GameObject.Find("Canvas");
    canvas.SetActive(false);
}

據我所知,這個播放器目前是服務器。

另一個玩家現在可以刷新列表並通過單擊按鈕加入此服務器,並使用MasterServer提供的HostData

private void HostButton(HostData hostData)
{
    Debug.Log(hostData.gameName);
    Network.Connect(hostData);
    Application.LoadLevel("GameScene");
}

如您所見,連接后已經加載了一個新場景。 建立連接后,我對服務器執行相同操作:

private void OnPlayerConnected(NetworkPlayer player)
{
    Debug.Log(player.externalIP + " Has connected!");       
    Application.LoadLevel("GameScene");
}

現在兩個玩家(客戶端和服務器)都在游戲場景中並且他們仍然連接。 我將如何輪到服務器並讓客戶端等待? 只需按下按鈕的反饋就足以讓我理解。 就像只允許單個玩家輸入反饋一樣。 這是我在新場景中嘗試的:

void Start () 
{
    players = Network.connections;
    foreach (NetworkPlayer player in players)
    {
        Debug.Log(player.externalIP + ":" + player.externalPort + " entered the game!");
    }
    Debug.Log(players.GetLength(0)); //returns 1. Obviously because server to client is one conncetion. But what is the NetworkPlayer of the server?
}

所以很明顯,下面的代碼來檢查哪個玩家可以行動是行不通的。

void Update () 
{
    if (players[currentPlayer] == Network.player)
    {
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log("Player " + (currentPlayer + 1) + " fired mouse!");
            currentPlayer++;
            if (currentPlayer > 1) currentPlayer = 0;
        }
    }
}

我完全被困了好幾天,所有關於網絡的教程都展示了兩個浮動的立方體,但根本沒有展示如何區分玩家。 如何限制單個玩家(無論他是創建服務器還是作為客戶端加入)在當前玩家采取行動之前移動

所以我在尋求有關如何在服務器玩家和連接的客戶端之間實現一個非常基本的回合制系統的提示。

雖然我自己從未使用過 MasterServer,但我相信 NetworkView.RPC 調用應該可以工作。 RPC 或遠程過程調用是通過網絡發送的調用,並在所有對等方上執行,前提是找到了匹配的公共方法。

我不會在這里介紹太多關於 RPC 的細節, Unity 的 NetworkView.RPC 文檔在這里有很詳細的介紹

對於您的問題,這里有一些您可以嘗試的代碼

創建一個新的 C# 腳本,並將其命名為RPCExample

RPCExample.cs

using UnityEngine;
using System.Collections;

public class RPCExample : MonoBehaviour {

    public static RPCExample instance;

    //Assign this NetworkView in the inspector
    public NetworkView networkView;

    //A boolean that states whether this player is the server
    //or the client
    public bool thisIsTheServer = false;

    //This is a boolean that will control whether it is THIS
    //player's turn or not
    public bool isMyTurn = false;


    void Awake () {
        instance = this;
    }

    //This method will set whether this connected player is the server or not
    [RPC]
    public void SetAsServer (bool isServer) {
        thisIsTheServer = isServer;
    }

//
    [RPC]
    public void SetTurn (bool turn) {
        isMyTurn = turn;
    }

    [RPC]
    public void FinishTurn () {
        networkView.RPC("SetTurn", RPCMode.Others, new object[] { true });
        SetTurn(false);
    }


    public void Update () {

        //It is not this player's turn, so early exit
        if(!isMyTurn)
            return;

        //If execution reaches here, it is this player's turn
        Debug.Log (string.Format("It is {0}'s turn!", 
                             new object[] { (thisIsTheServer) ? "Server" : "Client" }));

    }
}

接下來,將此腳本附加到您的玩家游戲對象,並在檢查器中分配 NetworkView 變量。

現在,將您的StartServer方法更改為

private void StartServer() {
    Network.InitializeServer(2, 25000, false);
    MasterServer.RegisterHost(gameName, "Test game 2", "Welcome!");
    GameObject canvas = GameObject.Find("Canvas");
    canvas.SetActive(false);

    //Set this player as server
    RPCExample.instance.SetAsServer(true);
}

更改您的HostButton方法如下

private void HostButton(HostData hostData) {
    Debug.Log(hostData.gameName);
    Network.Connect(hostData);
    Application.LoadLevel("GameScene");

    //This should only be executed on the client obviously.
    //Ensure you handle that scenario.
    RPCExample.instance.SetAsServer(false);
}

現在,對於這個例子,讓我們假設服務器總是先行(你可以很容易地改變它)。 因此,當您的游戲場景加載時(您使用 Application.LoadLevel("GameScene") 加載的那個),在客戶端調用以下方法

void Start () {
    //By calling FinishTurn on the client, we pass the turn onto the server
    //You can always rewrite this to use a random value, like a coin flip
    RPCExample.instance.FinishTurn();
}

就是這樣!。 當您完成當前玩家的回合后,只需調用

RPCExample.instance.FinishTurn();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM