文章目录
前言
此部分可以先建立游戏大厅,然后进入游戏,就像大部分rpg游戏一样,在进入游戏前有一个统一的大厅,此处坑甚多耗费大量时间。国内百度出来的基本没靠谱的,一些专栏作家大V也不过是基本翻译了一下用户手册(坑啊),只能通过看youtube视频以及不停的翻阅用户手册解决(很多demo根本没踩到这些坑)。废话不说了,开始(此部分是在上一篇基础上开始的,一些上一篇解释过的操作就不再重复),建议看完此部分后可以看一下下一篇,有助于理解此部分的代码。
1.自定义Lobby
1.1自定义NetworkLobbyManager
自定义脚本LobbyManager并重写NetworkLobbyManager的虚方法,惯例脚本在文末。
1.2 挂载脚本LobbyManager
挂载脚本是有讲究的,此脚本继承自NetworkLobbyManager。NetworkLobbyManager需要两个场景,即lobby场景和游戏场景,前者obby场景为准备场景(可以是像王者荣耀开始前队友列表UI,可以像吃鸡游戏开始之前的小岛场景),后者game场景即为真实游戏进行的场景。同时,对应的 需要两个参数lobby Player和gamePlayer,lobbyPlayer为进入lobby的游戏物体,game Player为真是游戏时的游戏物体。NetworkLobbyManager根据lobby场景中的lobbyPlayer在游戏场景中生成gamePlayer,但是当加载游戏场景后如果lobbyPlayer被销毁,则无法生成gamePlayer,所以加载场景时不能销毁。 而NetworkLobbyManager继承自NetworkManager,所以有DontDestroyOnLoad选项(自定义脚本不需要再继续添加DontDestroyOnLoad选项。而且在某些非常态lobby场景重新加载时(稍后会说到一些可能的重新加载场景)会有多个NetworkLobbyManager),所以生成的lobby Player最好是NetworkLobbyManager的子游戏物体。
1.3 游戏列表
游戏列表其实为了把unityService中建立的游戏进行列表,可供玩家选择加入。不同的游戏是通过LobbyMatch脚本控制,在游戏列表中把每一个LobbyMatch实例化出来
1.4 Player定义
gamePlayer与上上一篇(即example)中NetworkManager的game Player定义相同,必须包含NetworkIdentity和NetworkTransform(如果需要),在增加其他诸如移动,血量控制的脚本。lobbyPlayer则必须继承自Network LobbyPlayer。本篇通过自定义的LobbyPlayer(继承自Network LobbyPlayer)以及Lobby PlayerUI(lobby场景中LobbyPlayer为ui形态),两者脚本在文末。
PS:通过对NetworkLobbyManager应用发现很多坑,所幸基本坑都填上,坑实在太多,但是大部分均在代码中注释清楚,更加详细解释单独在下篇文章中解释。
2.完整脚本
2.1 LobbyManager
using UnityEngine.Networking;
using UnityEngine.Networking.Match;
using System;
using System.Collections.Generic;
using UnityEngine;
public class LobbyManager : NetworkLobbyManager
{
public static LobbyManager theLobbyManager;
#region OUTER ACITONS
public Action<MatchInfo> matchCreatedAction;
public Action<List<MatchInfoSnapshot>> matchListedAction;
public Action destroyMatchAction;
public Action dropConnAction;
public Action clientSceneChangedAction;
#endregion
#region HOST CALLBACKS
public override void OnStartHost()
{
LogInfo.theLogger.Log("Host create");
base.OnStartHost();
}
public override void OnStopHost()
{
LogInfo.theLogger.Log("Host stop");
base.OnStopHost();
}
public override void OnStopClient()
{
LogInfo.theLogger.Log("Host client");
base.OnStopClient();
}
public override void OnStartClient(NetworkClient lobbyClient)
{
LogInfo.theLogger.Log("Client create");
base.OnStartClient(lobbyClient);
}
public override GameObject OnLobbyServerCreateLobbyPlayer(NetworkConnection conn, short playerControllerId)
{
int num = 0;
foreach (var p in lobbySlots)
{
if (p != null)
{
num++;
}
}
LogInfo.theLogger.Log("ServerCreateLobbyPlayer:" + num);
return base.OnLobbyServerCreateLobbyPlayer(conn, playerControllerId); ;
}
public override GameObject OnLobbyServerCreateGamePlayer(NetworkConnection conn, short playerControllerId)
{
LogInfo.theLogger.Log("ServerCreateGamePlayer:" + lobbySlots.Length);
return base.OnLobbyServerCreateGamePlayer(conn, playerControllerId);
}
public override void OnLobbyServerPlayerRemoved(NetworkConnection conn, short playerControllerId)
{
LogInfo.theLogger.Log("LobbyServerPlayerRemoved");
base.OnLobbyServerPlayerRemoved(conn, playerControllerId);
}
public override void OnServerRemovePlayer(NetworkConnection conn, PlayerController player)
{
LogInfo.theLogger.Log("ServerRemovePlayer");
base.OnServerRemovePlayer(conn, player);
}
public override void OnLobbyClientSceneChanged(NetworkConnection conn)
{
LogInfo.theLogger.Log("LobbyClientSceneChanged");
base.OnLobbyClientSceneChanged(conn);
}
public override void OnLobbyServerPlayersReady()//当所有当前加入的player均准备后调用此方法,但加入的玩家数不一定定于maxPlayer
{
LogInfo.theLogger.Log("LobbyServerPlayersReady:"+lobbySlots.Length);
//base方法当所有加入的player均准备后进入游戏场景
//base.OnLobbyServerPlayersReady();
int readyPlayersNum = 0;
foreach(var player in lobbySlots)
{
if (player != null && player.readyToBegin) readyPlayersNum++;
}
if (readyPlayersNum == maxPlayers) BeginGame();