NetworkManager网络通讯_NetworkManager(二)

本文主要来实现一下自定UI(实现HUD的功能),并对Network Manger进行深入的讲解。

1)自定义manager

创建脚本CustomerUnetManger,并继承自NetworkManger,并对相关虚函数进行重载,并简单写了几个外部调用方法。完整脚本在文末,部分截图如下:

其中LogInfo为debug用,完整脚本在文末

2)UI脚本CustomerUnetMainMenu

编写脚本,实现自定义新建Server client 以及host,再次着重说一下原NetworkMangerHUD脚本中的第四个方法,即NetworkManger中的matchmaker。matchmaker通过unity提供的网络服务,建立游戏,然后通过你自己生成的exe就可以获取到建立的游戏列表,然后可以加入游戏:

首先开启matchmaker

    /// <summary>
    /// UI调用,MatchMaker
    /// </summary>
    public void StartMatchMaker_()
    {
        if (!IsClientConnected() && !NetworkServer.active && matchMaker == null)
        {
            StartMatchMaker();
            matchMode = true;
        }
    }

然后建立游戏

    /// <summary>
    /// UI调用,创建比赛
    /// </summary>
    public void CreateMatch_()
    {
        if (matchMaker != null)
        {
            matchMaker.CreateMatch("LLMatch", 3, true, "", "", "", 0, 0, OnMatchCreate);
        }
    }

获取游戏列表(获取列表并UI显示时需要脚本match Button)

matchMaker.ListMatches(0, 5, "", true, 0, 0, OnMatchList);

加入游戏

    /// <summary>
    /// 加入指定的比赛
    /// 对于建立比赛的player,本身已经在游戏中,所以不能再次加入(已经生成host)
    /// 对于建立比赛的player,在加入其他游戏时先取消比赛(DestroyMatch)
    /// 对于加入比赛的player,只能加入一次,不能重复加入(已经生成client)
    /// 对于加入比赛的Player,在重复加入或者加入其他游戏之前先断开连接(DropConnection)
    /// 本程序为demo,上述问题不做处理
    /// </summary>
    /// <param name="jointMatch"></param>
    public void JoinMatch(MatchInfoSnapshot jointMatch)
    {
        if (matchMaker == null) StartMatchMaker();

        matchMaker.JoinMatch(jointMatch.networkId, "", "", "", 0, 0, OnMatchJoined);//调用此方法时生成client
    }

 

3)此部分到此基本结束没有太大问题,一些注意事项已经在代码中注释,至于如何退出比赛等会再下一篇LobbyManager中进行解释,下边时此工程的所有脚本文件。再次说明一下,玩家预制体等均采用上一篇。此工程为demo,所以UI简陋,可能会有不友好的操作或者逻辑bug

 

 

//——————————————————————————————脚本————————————————————————————//

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.Match;

public class CustomerUnetManger : NetworkManager
{
    public Action<List<MatchInfoSnapshot>> ListMatchAction;

    private float refreshTime = 0;
    private bool matchMode = false;

    #region SERVER CALLBACKS
    public override void OnServerReady(NetworkConnection conn)
    {
        LogInfo.theLogger.Log("Server ready");

        base.OnServerReady(conn);
    }

    public override void OnStartServer()
    {
        LogInfo.theLogger.Log("Server start");

        base.OnStartServer();
    }

    public override void OnServerConnect(NetworkConnection conn)
    {
        LogInfo.theLogger.Log("Server connect");

        base.OnServerConnect(conn);
    }

    public override void OnServerDisconnect(NetworkConnection conn)
    {
        LogInfo.theLogger.Log("Server disconnect");

        base.OnServerDisconnect(conn);
    }

    public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    {
        LogInfo.theLogger.Log("Server add player");

        base.OnServerAddPlayer(conn, playerControllerId);
    }

    public override void OnServerRemovePlayer(NetworkConnection conn, PlayerController player)
    {
        LogInfo.theLogger.Log("Server remove player");

        base.OnServerRemovePlayer(conn, player);
    }

    public override void OnServerError(NetworkConnection conn, int errorCode)
    {
        LogInfo.theLogger.Log("Server error");

        base.OnServerError(conn, errorCode);
    }

    public override void OnStartHost()
    {
        LogInfo.theLogger.Log("Host start");

        base.OnStartHost();
    }

    public override void OnStopHost()
    {
        LogInfo.theLogger.Log("Host stop");

        base.OnStopHost();
    }

    public override void OnStopServer()
    {
        LogInfo.theLogger.Log("Server stop");

        base.OnStopServer();
    }
    #endregion

    #region CLIENT CALLBACKS
    public override void OnClientConnect(NetworkConnection conn)
    {
        LogInfo.theLogger.Log("Client connect");

        base.OnClientConnect(conn);
    }

    public override void OnClientDisconnect(NetworkConnection conn)
    {
        LogInfo.theLogger.Log("Client disconnect");

        base.OnClientDisconnect(conn);
    }

    public override void OnClientError(NetworkConnection conn, int errorCode)
    {
        LogInfo.theLogger.Log("Client error");

        base.OnClientError(conn, errorCode);
    }

    public override void OnStartClient(NetworkClient client)
    {
        LogInfo.theLogger.Log("Client start");

        base.OnStartClient(client);
    }

    public override void OnStopClient()
    {
        LogInfo.theLogger.Log("Client stop");

        base.OnStopClient();
    }
    #endregion

    #region MATCHMAKER CALLBACKS
    public override void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo)
    {
        LogInfo.theLogger.Log("Match create");

        //MatchCreate结束后进行OnMatchCreate回调,而在base中OnMatchCreate时会
        //立马创建host(即创建一个server和client),所以当重复创建match时报错
        //为避免此类问题可以在OnMatchCreate中不调用base的OnMatchCreate,通过自行创建List<MatchInfoSnapshot>变量自己存储比赛(matches)
        //然后在需要创建host时,再startHost,但是一般游戏时只允许玩家创建一个游戏,创建另一个游戏时需退出当前游戏
        base.OnMatchCreate(success, extendedInfo, matchInfo);
        matchMaker.ListMatches(0, 5, "", true, 0, 0, OnMatchList);
    }

    public override void OnMatchJoined(bool success, string extendedInfo, MatchInfo matchInfo)
    {
        LogInfo.theLogger.Log("Match joint");

        base.OnMatchJoined(success, extendedInfo, matchInfo);
    }

    public override void OnMatchList(bool success, string extendedInfo, List<MatchInfoSnapshot> matchList)
    {
        LogInfo.theLogger.Log("Match list:"+ matchList.Count);//基函数的OnMatchList把matchList赋值给matches,此处matches仍为初始值

        base.OnMatchList(success, extendedInfo, matchList);

        if(ListMatchAction!=null)
        {
            ListMatchAction(matchList);
        }
        //LogInfo.theLogger.Log("Match list:" + matches.Count);
    }
    #endregion

    #region CONTROLL METHODS
    /// <summary>
    /// UI调用,开启server
    /// </summary>
    public void StartServer_()
    {
        if (!IsClientConnected() && !NetworkServer.active && matchMaker == null)
        {
            StartServer();
        }
    }

    /// <summary>
    /// UI调用,开启Host
    /// </summary>
    public void StartHost_()
    {
        if (!IsClientConnected() && !NetworkServer.active && matchMaker == null)
        {
            StartHost();
        }
    }

    /// <summary>
    /// UI调用,开启client
    /// </summary>
    public void StartClient_()
    {
        if (!IsClientConnected() && !NetworkServer.active && matchMaker == null)
        {
            StartClient();
        }
    }

    /// <summary>
    /// UI调用,MatchMaker
    /// </summary>
    public void StartMatchMaker_()
    {
        if (!IsClientConnected() && !NetworkServer.active && matchMaker == null)
        {
            StartMatchMaker();
            matchMode = true;
        }
    }

    /// <summary>
    /// UI调用,停止服务
    /// </summary>
    public void StopAllService()
    {
        if (NetworkServer.active || IsClientConnected())
        {
            StopHost();
        }

        if (client != null && NetworkClient.active)
        {
            StopClient();
        }

        if (matchMaker != null)
        {
            StopMatchMaker();
            matchMode = false;
        }
    }

    /// <summary>
    /// UI调用,创建比赛
    /// </summary>
    public void CreateMatch_()
    {
        if (matchMaker != null)
        {
            matchMaker.CreateMatch("LLMatch", 3, true, "", "", "", 0, 0, OnMatchCreate);
        }
    }
    /// <summary>
    /// 加入指定的比赛
    /// 对于建立比赛的player,本身已经在游戏中,所以不能再次加入(已经生成host)
    /// 对于建立比赛的player,在加入其他游戏时先取消比赛(DestroyMatch)
    /// 对于加入比赛的player,只能加入一次,不能重复加入(已经生成client)
    /// 对于加入比赛的Player,在重复加入或者加入其他游戏之前先断开连接(DropConnection)
    /// 本程序为demo,上述问题不做处理
    /// </summary>
    /// <param name="jointMatch"></param>
    public void JoinMatch(MatchInfoSnapshot jointMatch)
    {
        if (matchMaker == null) StartMatchMaker();

        matchMaker.JoinMatch(jointMatch.networkId, "", "", "", 0, 0, OnMatchJoined);//调用此方法时生成client
    }
    #endregion

    private void Update()
    {
        //取消了实时更新列表,可以测试使用
        //if(Time.time>refreshTime && matchMode)
        //{
        //    if (matchMaker == null) StartMatchMaker();

        //    matchMaker.ListMatches(0, 5, "", true, 0, 0, OnMatchList);

        //    refreshTime += 4;
        //}        
    }
}

 

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.Match;
using UnityEngine.UI;

public class CustomerUnetMainMenu : MonoBehaviour
{
    public Button serverButton;
    public Button hostButton;
    public Button clinetButton;
    public Button matchMakerButton;
    public Button stopButton;
    public Button createMatchButton;

    public GameObject starts;
    public GameObject matches;
    public CustomerUnetManger theManager;
    public MatchListRefresher refresher;

    private bool matchCreated = false;

    #region BUTTON METHODS

    private void StartServer()
    {
        theManager.StartServer_();
    }

    private void StartHost()
    {
        theManager.StartHost_();
    }

    private void StartClient()
    {
        theManager.StartClient_();
    }

    private void StartMatchMaker()
    {
        theManager.StartMatchMaker_();

        matches.SetActive(true);
        starts.SetActive(false);
    }

    private void Stop()
    {
        theManager.StopAllService();

        matches.SetActive(false);
        starts.SetActive(true);
        matchCreated = false;
    }

    private void CreateMatch()
    {
        if(!matchCreated)
        {
            theManager.CreateMatch_();
            matchCreated = true;
        }
    }

    #endregion

    private void Start()
    {
        serverButton.onClick.AddListener(StartServer);
        hostButton.onClick.AddListener(StartHost);
        clinetButton.onClick.AddListener(StartClient);
        matchMakerButton.onClick.AddListener(StartMatchMaker);
        stopButton.onClick.AddListener(Stop);
        createMatchButton.onClick.AddListener(CreateMatch);

        theManager.ListMatchAction += OnListMatch;
    }

    private void OnListMatch(List<MatchInfoSnapshot> list)
    {
        refresher.RefreshList(list);
    }
}

 

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking.Match;

public class MatchListRefresher : MonoBehaviour
{
    [SerializeField]
    private GameObject matchButton;

    //直接清除列表的刷新的方式不好,可通过一下两种方法解决:
    //1、增加本地存储matches,针对每次反馈的matches比对,只实例化增加或者销毁不存在的
    //2、或者每次增加或者减少比赛,可以尝试让服务端调用每个客户端执行
    public void RefreshList(List<MatchInfoSnapshot> matches)
    {
        ClearList();

        foreach(var match in matches)
        {
            var button = Instantiate(matchButton, transform);
            button.GetComponent<MatchButton>().Initialize(match);
        }
    }

    private void ClearList()
    {
        foreach(Transform t in transform)
        {
            Destroy(t.gameObject);
        }
    }
}

 

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

public class MatchButton : MonoBehaviour
{
    private MatchInfoSnapshot match;
    //private NetworkManager manager;

    public void Initialize(MatchInfoSnapshot match)
    {
        this.match = match;

        GetComponentInChildren<Text>().text = match.name;
        GetComponent<Button>().onClick.AddListener(() =>
        {
            //manager.matchMaker.JoinMatch(match);
            FindObjectOfType<CustomerUnetManger>().JoinMatch(match);
        });
    }
}
using UnityEngine;
using UnityEngine.UI;

public class LogInfo : MonoBehaviour
{
    public bool isDebug = true;
    private Text log;

    public static LogInfo theLogger;

    public void Log(string info)
    {
        if(isDebug)
        log.text += "\r\n" + info;
    }

    private void Clear()
    {
        log.text = "Log:";
    }

    void Start ()
    {
        theLogger = this;
        log = GetComponent<Text>();
        log.text = "Log:";
        GetComponentInChildren<Button>().onClick.AddListener(Clear);
    }

}

 

posted @ 2018-07-08 16:35  81192  阅读(906)  评论(0编辑  收藏  举报