7.选服面板和功能串联

  1. 7.选服面板
    1. 7.1 数据准备
      1. 分析可知我们要创建服务器数据结构类和单条服务器数据结构类
      2. 创建服务器相关数据脚本类和单个服务器信息类,服务器相关数据类有一个存储单个服务器信息类的xml序列化字典。单个服务器信息类包含每条服务器要记录的必要的信息。每个信息变量加入 [XmlAttribute]特性,让单个服务器信息类是已属性的方式存储的,方便xml文件不用写很多尖括号。
      3. 服务器的数据一般默认都是配置好的,不是玩家操作产生的。单机游戏和联网游戏无非是配置数据是不是服务器下发的区别。在StreamingAssets文件夹创建xml文件,配置多条服务器数据。
      4. 在服务器面板初始化的时候测试加载XMl文件,查看序列化数据成不成功。测试完要删除。
    2. 7.2 拼面板
      1. 创建一个Panel取名为ChooseServerPanel,ChooseServerPanel下创建一个Texture作为面板的底图,拖拽服务器面板示意图,对着来拼
      2. 要有黑色背景作为半透明底图,直接复制提示面板的黑色半透明底图即可
      3. 创建一个Sprite,选择提示面板背景作为图片,调整切片模式九宫格透明度大小宽高锚点等,作为提示面板的面板背景,注意层级
      4. 创建选择服务器Sprite
      5. 把选服面板右侧的基础静态的ui逐渐拼好,包括一些背景图,选服文字,文本等。
      6. 创建左侧大tab选服的滚动视图,选择竖直滚动,这里的item是动态创建的
      7. 创建右侧大tab选服的滚动视图,选择竖直滚动,这里的item是动态创建的
      8. 创建左侧item按钮,适配后打成预设体。方便动态加载。添加Button和DrawScrollView脚本
      9. 创建右侧item按钮,适配后打成预设体。方便动态加载。添加Button和DrawScrollView脚本
    3. 7.3 左侧按钮功能
      1. 分析选服界面要创建的类。
      2. 创建选服左侧按钮ServerItem 脚本,自定义的组合性控件,归选服面板管理,不需要继承面板类。挂载到左侧按钮预制体上关联预制体上的控件。点击左侧按钮后刷新右侧按钮的事件监听待补充。。暴露给外部一个设置左侧按钮服务区区间的方法。
    4. 7.4 右侧按钮功能
      1. 创建选服右侧按钮脚本,归选服面板管理,不需要继承面板类。挂载到右侧按钮预制体上关联预制体上的控件。点击右侧按钮后隐藏选服面板显示刷新服务器面板的事件监听待补充。提供初始化右侧按钮信息的方法给选服面板使用,选服面板动态创建时调用即可。
    5. 7.5 动态创建按钮
      1. 登录管理器中添加服务器数据变量,初始化的时候加载服务器数据
      2. 创建选服面板ChooseServerPanel 脚本,继承面板基类。创建要用的控件变量,挂载到选服面板上关联对应控件。
      3. 选服面板内初始化的时候动态创建左侧按钮,因为左侧按钮服务器数据进行游戏的时候是不会变化的,所以初始化一次即可。
      4. 选服面板创建一个提供给左侧按钮动态刷新右侧按钮的方法。创建一个列表记录上一次刷新的右侧按钮。刷新前先删除之前的按钮对象并情况列表。得到服务器数据,遍历的创建右侧按钮预制体。设置右侧滚动视图为父对象动态计算位置。得到右侧按钮预制体上挂载的脚本进行右侧按钮信息的初始化。初始化完后记录到右侧按钮记录列表中。在左侧按钮脚本中添加点击当前按钮动态刷新右侧按钮的监听。
    6. 7.46 功能串联
      1. 重写选服面板显示方法,选服面板显示的时候应该初始化右侧按钮,并通过登录数据记录的上次登录的服务器id,显示上次登录的服务器。在服务器面板点击选服换区按钮时调用选服面板显示方法。
      2. 假如玩家从来没选过服务器,点击登录应该先跳到选服面板。选过服务器的话跳到服务器面板。修改登录面板登录按钮的事件监听。
      3. 右侧按钮类中点击右侧按钮的监听,点击后记录选择的服务器id到登录数据中,隐藏选服面板,显示服务器面板。重写服务器面板显示方法,通过得到更新后的登录数据服务器id进行数据的显示。但是注意这个最新的选服id并没有存进xml数据中。我们应该在服务器面板进入游戏按钮中添加监听,进入游戏就保存登录数据。
      4. 登录面板自动登录的逻辑还没有处理,登录面板初始化的时候处理自动登录面板逻辑,里面的内容拷贝确认登录的点击事件监听即可。
      5. 会发现面板脚本执行顺序的不同可能导致一个面板都不显示。比如登录面板初始化时由于自动登录让服务器面板显示,然而服务器面板后初始化时又自动让服务器面板隐藏。点击脚本中脚本执行顺序,添加Panel脚本设置其脚本执行先后应用执行顺序,解决这个问题。
      6. 在服务器面板添加一个返回按钮,在服务器面板脚本中关联并添加监听。
      7. 现在点击注册后,还会保留上一个玩家选择的服务器id,正常应该调到选服面板。登录管理器中添加注册成功重置数据的方法。注册面板确定按钮的点击事件监听中注册成功后把登录数据重置一下。
    7. 7.7 代码
      1. ServerInfo.xml
      2. ServerInfo
      3. ServerItem
      4. ServerChooseItem
      5. ChooseServerPanel
      6. LoginMgr
      7. ServerPanel

7.选服面板


7.1 数据准备

分析可知我们要创建服务器数据结构类和单条服务器数据结构类

创建服务器相关数据脚本类和单个服务器信息类,服务器相关数据类有一个存储单个服务器信息类的xml序列化字典。单个服务器信息类包含每条服务器要记录的必要的信息。每个信息变量加入 [XmlAttribute]特性,让单个服务器信息类是已属性的方式存储的,方便xml文件不用写很多尖括号。

/// <summary>
/// 服务器相关数据
/// </summary>
public class ServerInfo
{
    //一个服务器ID 对应一个服务器数据
    public SerizlizerDictionary<int, Server> serverDic = new SerizlizerDictionary<int, Server>();
}

/// <summary>
/// 单个服务器信息
/// </summary>
public class Server
{
    [XmlAttribute]
    public int id;//服务器ID 区号
    [XmlAttribute]
    public string name;//服务器名字
    [XmlAttribute]
    public int state;//服务器状态
    [XmlAttribute]
    public bool isNew;//是否是新服
}

服务器的数据一般默认都是配置好的,不是玩家操作产生的。单机游戏和联网游戏无非是配置数据是不是服务器下发的区别。在StreamingAssets文件夹创建xml文件,配置多条服务器数据。

<?xml version="1.0" encoding="UTF-8"?>
<ServerInfo>
    <serverDic>
        <int>1</int>
        <Server id="1" name="天下无双1区" state="0" isNew="false"/>
        <int>2</int>
        <Server id="2" name="天下无双2区" state="1" isNew="false"/>
        <int>3</int>
        <Server id="3" name="天下无双3区" state="2" isNew="false"/>
        <int>4</int>
        <Server id="4" name="天下无双4区" state="3" isNew="false"/>
        <int>5</int>
        <Server id="5" name="天下无双5区" state="4" isNew="false"/>
        <int>6</int>
        <Server id="6" name="天下无双6区" state="0" isNew="false"/>
        <int>7</int>
        <Server id="7" name="天下无双7区" state="1" isNew="false"/>
        <int>8</int>
        <Server id="8" name="天下无双8区" state="2" isNew="false"/>
        <int>9</int>
        <Server id="9" name="天下无双9区" state="3" isNew="false"/>
        <int>10</int>
        <Server id="10" name="天下无双10区" state="4" isNew="false"/>
        <int>11</int>
        <Server id="11" name="天下无双11区" state="0" isNew="false"/>
        <int>12</int>
        <Server id="12" name="天下无双12区" state="1" isNew="false"/>
        <int>13</int>
        <Server id="13" name="天下无双13区" state="2" isNew="false"/>
        <int>14</int>
        <Server id="14" name="天下无双14区" state="3" isNew="false"/>
        <int>15</int>
        <Server id="15" name="天下无双15区" state="4" isNew="false"/>
        <int>16</int>
        <Server id="16" name="天下无双16区" state="4" isNew="true"/>
        <int>17</int>
        <Server id="17" name="天下无双17区" state="4" isNew="true"/>
        <int>18</int>
        <Server id="18" name="天下无双18区" state="4" isNew="true"/>
    </serverDic>
</ServerInfo>

在服务器面板初始化的时候测试加载XMl文件,查看序列化数据成不成功。测试完要删除。


7.2 拼面板

创建一个Panel取名为ChooseServerPanel,ChooseServerPanel下创建一个Texture作为面板的底图,拖拽服务器面板示意图,对着来拼

要有黑色背景作为半透明底图,直接复制提示面板的黑色半透明底图即可

创建一个Sprite,选择提示面板背景作为图片,调整切片模式九宫格透明度大小宽高锚点等,作为提示面板的面板背景,注意层级

创建选择服务器Sprite

把选服面板右侧的基础静态的ui逐渐拼好,包括一些背景图,选服文字,文本等。

创建左侧大tab选服的滚动视图,选择竖直滚动,这里的item是动态创建的

创建右侧大tab选服的滚动视图,选择竖直滚动,这里的item是动态创建的

创建左侧item按钮,适配后打成预设体。方便动态加载。添加Button和DrawScrollView脚本


创建右侧item按钮,适配后打成预设体。方便动态加载。添加Button和DrawScrollView脚本



7.3 左侧按钮功能

分析选服界面要创建的类。

创建选服左侧按钮ServerItem 脚本,自定义的组合性控件,归选服面板管理,不需要继承面板类。挂载到左侧按钮预制体上关联预制体上的控件。点击左侧按钮后刷新右侧按钮的事件监听待补充。。暴露给外部一个设置左侧按钮服务区区间的方法。

/// <summary>
/// 选服左侧按钮 自定义的组合性控件 归选服面板管理 不需要继承面板类
/// </summary>
public class ServerItem : MonoBehaviour
{
    //按钮自己
    public UIButton btn;
    //显示的内容
    public UILabel labInfo;

    //记录按钮代表的区间 
    private int beginIndex;
    private int endIndex;

    void Start()
    {
        btn.onClick.Add(new EventDelegate(()=> { 
            //点击按钮过后 做什么 
            //要动态更新右侧按钮
        }));
    }

    //外部动态创建该按钮时 用于初始化 告诉其 从多少区到多少区
    public void InitInfo(int beginIndex, int endIndex)
    {
        //记录按钮代表的区间 用于之后 动态创建 单个服务器内容
        this.beginIndex = beginIndex;
        this.endIndex = endIndex;

        //改变显示的区间内容
        labInfo.text = beginIndex + " - " + endIndex + "区";
    }
}

7.4 右侧按钮功能

创建选服右侧按钮脚本,归选服面板管理,不需要继承面板类。挂载到右侧按钮预制体上关联预制体上的控件。点击右侧按钮后隐藏选服面板显示刷新服务器面板的事件监听待补充。提供初始化右侧按钮信息的方法给选服面板使用,选服面板动态创建时调用即可。

//选服右侧按钮
public class ServerChooseItem : MonoBehaviour
{
    //按钮本身
    public UIButton btnChooseServer;
    //服务器名字
    public UILabel labName;
    //是否是新服
    public UISprite sprNew;
    //状态
    public UISprite sprState;

    //当前这个按钮 代表的单个服务器信息 之后 用于传给我们的服务器面板
    private Server nowInfo;

    void Start()
    {
        btnChooseServer.onClick.Add(new EventDelegate(() => {
            //当点击了 这个单个服务器按钮 要做什么

            //隐藏选服面板

            //显示服务器面板

            //更新服务器面板
        }));
    }

    //初始化右侧按钮的方法 提供给选服面板使用
    public void InitInfo(Server info)
    {
        //记录传入的初始化信息
        nowInfo = info;

        //根据传入的单个服务器数据 进行更新

        //显示内容更新
        //名字
        labName.text = info.id + "区  " + info.name;
        //是否显示new 是不是新服
        sprNew.gameObject.SetActive(info.isNew);
        //状态
        sprState.gameObject.SetActive(true);
        switch (info.state)
        {
            case 0:
                sprState.gameObject.SetActive(false);
                break;
            case 1:
                sprState.spriteName = "ui_DL_liuchang_01";
                break;
            case 2:
                sprState.spriteName = "ui_DL_fanhua_01";
                break;
            case 3:
                sprState.spriteName = "ui_DL_huobao_01";
                break;
            case 4:
                sprState.spriteName = "ui_DL_weihu_01";
                break;
        }
    }
}

7.5 动态创建按钮

登录管理器中添加服务器数据变量,初始化的时候加载服务器数据

/// <summary>
/// 登录管理器 主要用于管理 登录相关的数据
/// </summary>
public class LoginMgr
{
    private LoginMgr() 
    {
        //获取服务器数据
        serverInfo = XmlDataMgr.Instance.LoadData(typeof(ServerInfo), "ServerInfo") as ServerInfo;
    }

    //服务器数据
    private ServerInfo serverInfo;
    //方便外部获取 为了安全
    public ServerInfo ServerInfo => serverInfo;
}

创建选服面板ChooseServerPanel 脚本,继承面板基类。创建要用的控件变量,挂载到选服面板上关联对应控件。

//选服面板 继承面板基类
public class ChooseServerPanel : BasePanel<ChooseServerPanel>
{
    //左右两个 滚动视图 的位置信息 主要用来在下面创建子对象
    public Transform svLeft;
    public Transform svRight;

    //上次登录的服务器名
    public UILabel labName;
    public UISprite sprState;

    //当前选择的服务器区间文字
    public UILabel labNowServer;
}

选服面板内初始化的时候动态创建左侧按钮,因为左侧按钮服务器数据进行游戏的时候是不会变化的,所以初始化一次即可。

public override void Init()
{
    //因为左侧 按钮 服务器数据 进行游戏的时候 是不会变化的 所以初始化一次即可

    //动态创建左侧按钮

    //得到服务器数据
    ServerInfo info = LoginMgr.Instance.ServerInfo;

    //得到要循环几次 左侧按钮按5区一间隔区分
    int num = info.serverDic.Count / 5 + 1;

    //动态创建左侧按钮
    for (int i = 0; i < num; i++)
    {
        //创建一个一个的按钮
        GameObject item = Instantiate(Resources.Load<GameObject>("UI/btnServer"));
        //设置父对象 设置位置
        item.transform.SetParent(svLeft, false);
        //每个左侧按钮往下偏移
        item.transform.localPosition = new Vector3(-79, 58, 0) + new Vector3(0, -65 * i, 0);
        //得到脚本 进行按钮信息初始化
        ServerItem serverItem = item.GetComponent<ServerItem>();
        //得到当前按钮 代表的服务器区间
        int beginIndex = 5 * i + 1;
        int endIndex = 5 * (i + 1);
        //判断 最大 是不是超过的 服务器的总数
        if (endIndex > info.serverDic.Count)
            endIndex = info.serverDic.Count;
        //调用左侧按钮初始化信息的方法
        serverItem.InitInfo(beginIndex, endIndex);
    }
}

选服面板创建一个提供给左侧按钮动态刷新右侧按钮的方法。创建一个列表记录上一次刷新的右侧按钮。刷新前先删除之前的按钮对象并情况列表。得到服务器数据,遍历的创建右侧按钮预制体。设置右侧滚动视图为父对象动态计算位置。得到右侧按钮预制体上挂载的脚本进行右侧按钮信息的初始化。初始化完后记录到右侧按钮记录列表中。在左侧按钮脚本中添加点击当前按钮动态刷新右侧按钮的监听。

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

//选服面板 继承面板基类
public class ChooseServerPanel : BasePanel<ChooseServerPanel>
{
    //左右两个 滚动视图 的位置信息 主要用来在下面创建子对象
    public Transform svLeft;
    public Transform svRight;

    //当前选择的服务器区间文字
    public UILabel labNowServer;

    //记录之前显示的 单个服务器按钮们
    private List<GameObject> itemList = new List<GameObject>();

    //提供方法给外部 用于更新面板右侧的按钮显示内容
    public void UpdatePanel(int beginIndex, int endIndex)
    {
        //更新当前选择的服务器区间 显示
        labNowServer.text = "服务器" + beginIndex + "—" + endIndex + "区";

        //创建新的按钮之前 应该删除老的
        for (int i = 0; i < itemList.Count; i++)
        {
            //删除依附的对象
            Destroy(itemList[i].gameObject);
        }
        //删除后 并没有清空列表 所以需要手动清空列表
        itemList.Clear();

        //创建新的按钮
        Server nowInfo;
        for (int i = beginIndex; i <= endIndex; i++)
        {
            //获取单个服务器数据
            nowInfo = LoginMgr.Instance.ServerInfo.serverDic[i];

            //动态创建按钮 放置位置即可
            GameObject serverItem = Instantiate(Resources.Load<GameObject>("UI/btnChooseServer"));

            //设置父对象为滚动视图
            serverItem.transform.SetParent(svRight, false);

            //区间不是从0开始的 1-5 6-10 11-15 这样的 (i-1) % 5是强行变得从0开始 %2是判断奇数偶数 奇数要x偏移300  /2是因为一排有两个 得出来的值往y要下偏多少个80
            serverItem.transform.localPosition = new Vector3(-8, 61, 0) + new Vector3( (i-1) % 5 % 2*300, (i - 1) % 5 / 2*-80, 0);

            //得到按钮上的脚本 根据服务器信息 更新内容即可
            ServerChooseItem chooseItem = serverItem.GetComponent<ServerChooseItem>();

            //初始化右侧按钮
            chooseItem.InitInfo(nowInfo);

            //创建成功后 把它记录到列表中 方便下次删除
            itemList.Add(serverItem);
        }
    }
}


/// <summary>
/// 自定义的组合性空间 归选服面板管理 不需要继承面板类
/// </summary>
public class ServerItem : MonoBehaviour
{
    //按钮自己
    public UIButton btn;
    //显示的内容
    public UILabel lab

Info;

    private int beginIndex;
    private int endIndex;

    void Start()
    {
        btn.onClick.Add(new EventDelegate(()=> {
            //点击按钮过后 做什么 
            //通知 切换服务器面板 更新右侧 按钮内容
            ChooseServerPanel.Instance.UpdatePanel(beginIndex, endIndex);
        }));
    }

    //外部动态创建该按钮时 用于初始化 告诉其 从多少区到多少区
    public void InitInfo(int beginIndex, int endIndex)
    {
        //记录按钮代表的区间 用于之后 动态创建 单个服务器内容
        this.beginIndex = beginIndex;
        this.endIndex = endIndex;

        //改变显示的区间内容
        labInfo.text = beginIndex + " - " + endIndex + "区";
    }    
}

7.46 功能串联

重写选服面板显示方法,选服面板显示的时候应该初始化右侧按钮,并通过登录数据记录的上次登录的服务器id,显示上次登录的服务器。在服务器面板点击选服换区按钮时调用选服面板显示方法。

//选服面板显示方法
public override void ShowMe()
{
    base.ShowMe();
    //初始化面板显示
    //1.初始化上一次服务器相关内容显示
    if (LoginMgr.Instance.LoginData.frontServerID == 0)
    {
        //没选择过服务器 设置上次选的服务器为0 不显示火爆等
        labName.text = "无";
        sprState.gameObject.SetActive(false);
    }
    else
    {
        //选择过服务器
        //通过登录数据中的上一次服务器id 得到单个服务器信息 然后去显示
        Server info = LoginMgr.Instance.ServerInfo.serverDic[LoginMgr.Instance.LoginData.frontServerID];
        //拼接显示上一次的服务器名字 显示火爆图片
        labName.text = info.id + "区  " + info.name;
        sprState.gameObject.SetActive(true);
        //根据状态 改变图片的显示
        switch (info.state)
        {
            case 0:
                sprState.gameObject.SetActive(false);
                break;
            case 1:
                sprState.spriteName = "ui_DL_liuchang_01";
                break;
            case 2:
                sprState.spriteName = "ui_DL_fanhua_01";
                break;
            case 3:
                sprState.spriteName = "ui_DL_huobao_01";
                break;
            case 4:
                sprState.spriteName = "ui_DL_weihu_01";
                break;
        }
    }
    //2.更新右侧按钮显示 默认显示1-5
    //最大索引要判断
    UpdatePanel(1, 5 > LoginMgr.Instance.ServerInfo.serverDic.Count ? LoginMgr.Instance.ServerInfo.serverDic.Count : 5);
}

//服务器面板换区按钮监听
btnChange.onClick.Add(new EventDelegate(()=> {
    //打开服务区选择面板
    ChooseServerPanel.Instance.ShowMe();
    //隐藏自己
    HideMe();
}));

假如玩家从来没选过服务器,点击登录应该先跳到选服面板。选过服务器的话跳到服务器面板。修改登录面板登录按钮的事件监听。

//登录面板登录按钮事件监听
btnLogin.onClick.Add(new EventDelegate(() => {
    //点击登录做啥
    //判断 找好和密码 是否合法 
    //合法 做什么
    if( LoginMgr.Instance.CheckInfo(inputUserName.value, inputPassWord.value) )
    {
        //记录用户名
        LoginMgr.Instance.LoginData.userName = inputUserName.value;
        LoginMgr.Instance.LoginData.passWord = inputPassWord.value;
        LoginMgr.Instance.LoginData.rememberPW = togRemeber.value;
        LoginMgr.Instance.LoginData.autoLogin = togAutoLogin.value;
        LoginMgr.Instance.SaveLoginData();
        //隐藏自己 显示 服务器相关面板
        //如果玩家之前选择过服务器 
        //直接打开服务器面板
        if( LoginMgr.Instance.LoginData.frontServerID == 0 )
        {
            ChooseServerPanel.Instance.ShowMe();
        }
        //如果没有选择过服务器 那就打开服务器选择面板
        else
        {
            ServerPanel.Instance.ShowMe();
        }
        HideMe();
    }
    //不合法做什么
    else
    {
        TipPanel.Instance.ShowMe();
        TipPanel.Instance.ChangeInfo("账号或密码错误");
    }
}));

右侧按钮类中点击右侧按钮的监听,点击后记录选择的服务器id到登录数据中,隐藏选服面板,显示服务器面板。重写服务器面板显示方法,通过得到更新后的登录数据服务器id进行数据的显示。但是注意这个最新的选服id并没有存进xml数据中。我们应该在服务器面板进入游戏按钮中添加监听,进入游戏就保存登录数据。

//右侧按钮类中点击右侧按钮的监听 
btnChooseServer.onClick.Add(new EventDelegate(() => {
    //当点击了 这个单个服务器按钮 要做什么
    //记录当前玩家 选择的服务器ID
    LoginMgr.Instance.LoginData.frontServerID = nowInfo.id;
    //隐藏选服面板
    ChooseServerPanel.Instance.HideMe();
    //显示服务器面板
    //更新服务器面板
    ServerPanel.Instance.ShowMe();
}));

//服务器面板显示方法
public override void ShowMe()
{
    base.ShowMe();
    //之后再这里更新 lab显示的服务器信息即可
    //根据玩家上一次的服务器ID 从登录管理器中得到数据 进行更新
    int id = LoginMgr.Instance.LoginData.frontServerID;
    Server info = LoginMgr.Instance.ServerInfo.serverDic[id];
    labInfo.text = info.name;
}

//服务器面板进入游戏按钮监听
btnBegin.onClick.Add(new EventDelegate(()=> {
    //真正进入游戏了 那么久再存储一次登录数据 把服务器ID存下来
    LoginMgr.Instance.SaveLoginData();
    //进去游戏 场景切换
    SceneManager.LoadScene("GameScene");
}));

登录面板自动登录的逻辑还没有处理,登录面板初始化的时候处理自动登录面板逻辑,里面的内容拷贝确认登录的点击事件监听即可。

//是否自动登录
if( data.autoLogin )
{
    //自动登录的逻辑
    //判断 找好和密码 是否合法 
    //合法 做什么
    if (LoginMgr.Instance.CheckInfo(inputUserName.value, inputPassWord.value))
    {
        //隐藏自己 显示 服务器相关面板
        //如果玩家之前选择过服务器 
        //直接打开服务器面板
        if (LoginMgr.Instance.LoginData.frontServerID == 0)
        {
            ChooseServerPanel.Instance.ShowMe();
        }
        //如果没有选择过服务器 那就打开服务器选择面板
        else
        {
            ServerPanel.Instance.ShowMe();
        }
        HideMe();
    }
    //不合法做什么
    else
    {
        TipPanel.Instance.ShowMe();
        TipPanel.Instance.ChangeInfo("账号或密码错误");
    }
}

会发现面板脚本执行顺序的不同可能导致一个面板都不显示。比如登录面板初始化时由于自动登录让服务器面板显示,然而服务器面板后初始化时又自动让服务器面板隐藏。点击脚本中脚本执行顺序,添加Panel脚本设置其脚本执行先后应用执行顺序,解决这个问题。




在服务器面板添加一个返回按钮,在服务器面板脚本中关联并添加监听。

//返回按钮
public UIButton btnBack;

public override void Init()
{
    btnBack.onClick.Add(new EventDelegate(() => {
        //返回登录面板
        LoginPanel.Instance.ShowMe();
        HideMe();
    }));
}

现在点击注册后,还会保留上一个玩家选择的服务器id,正常应该调到选服面板。登录管理器中添加注册成功重置数据的方法。注册面板确定按钮的点击事件监听中注册成功后把登录数据重置一下。

//登录管理器中 注册成功后 应该把上一次别人登录的 id清空
public void ClearLoginData()
{
    loginData.frontServerID = 0;
}

//注册面板确定按钮的点击事件监听
btnSure.onClick.Add(new EventDelegate(() => {
    //点击确定进行注册
    //判断输入的账号密码 是否合理
    if( inputUserName.value.Length <= 6 ||
        inputPassWord.value.Length <= 6)
    {
        //显示提示面板
        TipPanel.Instance.ShowMe();
        //改变提示面板上显示的内容
        TipPanel.Instance.ChangeInfo("账号和密码都必须大于6位");
        return;
    }
    //注册用户
    //如果注册成功做什么
    if( LoginMgr.Instance.RegisterUser(inputUserName.value, inputPassWord.value) )
    {
        //注册成功 就可以显示 登录面板 隐藏注册面板
        //显示登录面板
        LoginPanel.Instance.ShowMe();
        //希望把登录面板上的用户名和密码 设置的 和你注册时一样 方便玩家操作
        LoginPanel.Instance.SetInfo(inputUserName.value, inputPassWord.value);
        //注册成功后 把登录数据 重置一下 
        LoginMgr.Instance.ClearLoginData();
        //隐藏注册面板
        HideMe();
    }
    //如果注册失败做什么
    else
    {
        //提示别人 用户名已经存在 注册失败
        TipPanel.Instance.ChangeInfo("用户名已存在");
        TipPanel.Instance.ShowMe();
    }
}));

7.7 代码

ServerInfo.xml

<?xml version="1.0" encoding="UTF-8"?>
<ServerInfo>
    <serverDic>
        <int>1</int>
        <Server id="1" name="天下无双1区" state="0" isNew="false"/>
        <int>2</int>
        <Server id="2" name="天下无双2区" state="1" isNew="false"/>
        <int>3</int>
        <Server id="3" name="天下无双3区" state="2" isNew="false"/>
        <int>4</int>
        <Server id="4" name="天下无双4区" state="3" isNew="false"/>
        <int>5</int>
        <Server id="5" name="天下无双5区" state="4" isNew="false"/>
        <int>6</int>
        <Server id="6" name="天下无双6区" state="0" isNew="false"/>
        <int>7</int>
        <Server id="7" name="天下无双7区" state="1" isNew="false"/>
        <int>8</int>
        <Server id="8" name="天下无双8区" state="2" isNew="false"/>
        <int>9</int>
        <Server id="9" name="天下无双9区" state="3" isNew="false"/>
        <int>10</int>
        <Server id="10" name="天下无双10区" state="4" isNew="false"/>
        <int>11</int>
        <Server id="11" name="天下无双11区" state="0" isNew="false"/>
        <int>12</int>
        <Server id="12" name="天下无双12区" state="1" isNew="false"/>
        <int>13</int>
        <Server id="13" name="天下无双13区" state="2" isNew="false"/>
        <int>14</int>
        <Server id="14" name="天下无双14区" state="3" isNew="false"/>
        <int>15</int>
        <Server id="15" name="天下无双15区" state="4" isNew="false"/>
        <int>16</int>
        <Server id="16" name="天下无双16区" state="4" isNew="true"/>
        <int>17</int>
        <Server id="17" name="天下无双17区" state="4" isNew="true"/>
        <int>18</int>
        <Server id="18" name="天下无双18区" state="4" isNew="true"/>
    </serverDic>
</ServerInfo>

ServerInfo

using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using UnityEngine;

/// <summary>
/// 服务器相关数据
/// </summary>
public class ServerInfo
{
    //一个服务器ID 对应一个服务器数据
    public SerizlizerDictionary<int, Server> serverDic = new SerizlizerDictionary<int, Server>();
}

/// <summary>
/// 单个服务器信息
/// </summary>
public class Server
{
    [XmlAttribute]
    public int id;//服务器ID 区号
    [XmlAttribute]
    public string name;//服务器名字
    [XmlAttribute]
    public int state;//服务器状态
    [XmlAttribute]
    public bool isNew;//是否是新服
}

ServerItem

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

/// <summary>
/// 自定义的组合性空间 归选服面板管理 不需要继承面板类
/// </summary>
public class ServerItem : MonoBehaviour
{
    //按钮自己
    public UIButton btn;
    //显示的内容
    public UILabel labInfo;

    private int beginIndex;
    private int endIndex;

    void Start()
    {
        btn.onClick.Add(new EventDelegate(()=> {
            //点击按钮过后 做什么 
            //通知 切换服务器面板 更新右侧 按钮内容
            ChooseServerPanel.Instance.UpdatePanel(beginIndex, endIndex);
        }));
    }

    //外部动态创建该按钮时 用于初始化 告诉其 从多少区到多少区
    public void InitInfo(int beginIndex, int endIndex)
    {
        //记录按钮代表的区间 用于之后 动态创建 单个服务器内容
        this.beginIndex = beginIndex;
        this.endIndex = endIndex;

        //改变显示的区间内容
        labInfo.text = beginIndex + " - " + endIndex + "区";
    }
    
}

ServerChooseItem

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

public class ServerChooseItem : MonoBehaviour
{
    //按钮本身
    public UIButton btnChooseServer;
    //服务器名字
    public UILabel labName;
    //是否是新服
    public UISprite sprNew;
    //状态
    public UISprite sprState;

    //当前这个按钮 代表的单个服务器信息 之后 用于传给我们的服务器面板
    private Server nowInfo;

    void Start()
    {
        //右侧按钮类中点击右侧按钮的监听 
        btnChooseServer.onClick.Add(new EventDelegate(() => {
            //当点击了 这个单个服务器按钮 要做什么

            //记录当前玩家 选择的服务器ID
            LoginMgr.Instance.LoginData.frontServerID = nowInfo.id;

            //隐藏选服面板
            ChooseServerPanel.Instance.HideMe();
            //显示服务器面板
            //更新服务器面板
            ServerPanel.Instance.ShowMe();
        }));
    }

    public void InitInfo(Server info)
    {
        //记录传入的初始化信息
        nowInfo = info;

        //根据传入的单个服务器数据 进行更新

        //显示内容更新
        //名字
        labName.text = info.id + "区  " + info.name;
        //是否显示new 是不是新服
        sprNew.gameObject.SetActive(info.isNew);
        //状态
        sprState.gameObject.SetActive(true);

        //根据状态不一样更新图片
        switch (info.state)
        {
            case 0:
                sprState.gameObject.SetActive(false);
                break;
            case 1:
                sprState.spriteName = "ui_DL_liuchang_01";
                break;
            case 2:
                sprState.spriteName = "ui_DL_fanhua_01";
                break;
            case 3:
                sprState.spriteName = "ui_DL_huobao_01";
                break;
            case 4:
                sprState.spriteName = "ui_DL_weihu_01";
                break;
        }
    }
}

ChooseServerPanel

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

public class ChooseServerPanel : BasePanel<ChooseServerPanel>
{
    //左右两个 滚动视图 的位置信息 主要用来在下面创建子对象
    public Transform svLeft;
    public Transform svRight;

    //上次登录的服务器名
    public UILabel labName;
    public UISprite sprState;

    //当前选择的服务器区间文字
    public UILabel labNowServer;

    //记录之前显示的 单个服务器按钮们
    private List<GameObject> itemList = new List<GameObject>();

    public override void Init()
    {
        //因为左侧 按钮 服务器数据 进行游戏的时候 是不会变化的 所以初始化一次即可

        //动态创建左侧按钮
        ServerInfo info = LoginMgr.Instance.ServerInfo;

        //得到要循环几次 按5区一间隔区分
        int num = info.serverDic.Count / 5 + 1;

        for (int i = 0; i < num; i++)
        {
            //创建一个一个的按钮
            GameObject item = Instantiate(Resources.Load<GameObject>("UI/btnServer"));
            //设置父对象 设置位置
            item.transform.SetParent(svLeft, false);
            item.transform.localPosition = new Vector3(-79, 58, 0) + new Vector3(0, -65 * i, 0);
            //得到脚本 进行按钮信息初始化
            ServerItem serverItem = item.GetComponent<ServerItem>();
            //得到当前按钮 代表的服务器区间
            int beginIndex = 5 * i + 1;
            int endIndex = 5 * (i + 1);
            //判断 最大 是不是超过的 服务器的总数
            if (endIndex > info.serverDic.Count)
                endIndex = info.serverDic.Count;
            serverItem.InitInfo(beginIndex, endIndex);
        }

        //一开始隐藏自己
        HideMe();
    }

    //提供方法给外部 用于更新面板右侧的按钮显示内容
    public void UpdatePanel(int beginIndex, int endIndex)
    {
        //更新当前选择的服务器区间 显示
        labNowServer.text = "服务器" + beginIndex + "—" + endIndex + "区";

        //创建新的按钮之前 应该删除老的
        for (int i = 0; i < itemList.Count; i++)
        {
            //删除依附的对象
            Destroy(itemList[i].gameObject);
        }
        //删除后 并没有清空列表 所以需要手动清空列表
        itemList.Clear();

        //创建新的按钮
        Server nowInfo;
        for (int i = beginIndex; i <= endIndex; i++)
        {
            //获取单个服务器数据
            nowInfo = LoginMgr.Instance.ServerInfo.serverDic[i];

            //动态创建按钮 放置位置即可
            GameObject serverItem = Instantiate(Resources.Load<GameObject>("UI/btnChooseServer"));
            serverItem.transform.SetParent(svRight, false);
            serverItem.transform.localPosition = new Vector3(-8, 61, 0) + new Vector3( (i-1) % 5 % 2*300, (i - 1) % 5 / 2*-80, 0);

            //得到按钮上的脚本 根据服务器信息 更新内容即可
            ServerChooseItem chooseItem = serverItem.GetComponent<ServerChooseItem>();
            chooseItem.InitInfo(nowInfo);

            //创建成功后 把它记录到列表中 方便下次删除
            itemList.Add(serverItem);
        }
    }

    //选服面板显示方法
    public override void ShowMe()
    {
        base.ShowMe();
        //初始化面板显示
        //1.初始化上一次服务器相关内容显示
        if (LoginMgr.Instance.LoginData.frontServerID == 0)
        {
            //没选择过服务器 设置上次选的服务器为0 不显示火爆等
            labName.text = "无";
            sprState.gameObject.SetActive(false);
        }
        else
        {
            //选择过服务器

            //通过登录数据中的上一次服务器id 得到单个服务器信息 然后去显示
            Server info = LoginMgr.Instance.ServerInfo.serverDic[LoginMgr.Instance.LoginData.frontServerID];

            //拼接显示上一次的服务器名字 显示火爆图片
            labName.text = info.id + "区  " + info.name;
            sprState.gameObject.SetActive(true);

            //根据状态 改变图片的显示
            switch (info.state)
            {
                case 0:
                    sprState.gameObject.SetActive(false);
                    break;
                case 1:
                    sprState.spriteName = "ui_DL_liuchang_01";
                    break;
                case 2:
                    sprState.spriteName = "ui_DL_fanhua_01";
                    break;
                case 3:
                    sprState.spriteName = "ui_DL_huobao_01";
                    break;
                case 4:
                    sprState.spriteName = "ui_DL_weihu_01";
                    break;
            }
        }

        //2.更新右侧按钮显示 默认显示1-5
        //最大索引要判断
        UpdatePanel(1, 5 > LoginMgr.Instance.ServerInfo.serverDic.Count ? LoginMgr.Instance.ServerInfo.serverDic.Count : 5);
    }
}

LoginMgr

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

/// <summary>
/// 登录管理器 主要用于管理 登录相关的数据
/// </summary>
public class LoginMgr
{
    private static LoginMgr instance = new LoginMgr();
    public static LoginMgr Instance => instance;

    private LoginMgr() 
    {
        //获取登录面板数据 从xml文件中获取
        loginData = XmlDataMgr.Instance.LoadData(typeof(LoginData), "LoginData") as LoginData;
        //获取注册数据 从xml文件中获取
        registerData = XmlDataMgr.Instance.LoadData(typeof(RegisterData), "RegisterData") as RegisterData;
        //获取服务器数据
        serverInfo = XmlDataMgr.Instance.LoadData(typeof(ServerInfo), "ServerInfo") as ServerInfo;
    }

    //服务器数据
    private ServerInfo serverInfo;
    //方便外部获取 为了安全
    public ServerInfo ServerInfo => serverInfo;


    //所有玩家的注册数据
    private RegisterData registerData;
    //为了安全 提供一个 只能得不能改的 属性给外部
    public RegisterData RegisterData => registerData;
    //存储注册数据
    public void SaveRegisterData()
    {
        XmlDataMgr.Instance.SaveData(registerData, "RegisterData");
    }


    //提供给外部注册的方法 返回值 代表是否注册成功
    public bool RegisterUser(string userName, string passWord)
    {
        //判断是否重复了用户名
        if(registerData.registerInfo.ContainsKey(userName))
        {
            return false;
        }
        //记录注册信息
        //添加到字典中进行记录
        registerData.registerInfo.Add(userName, passWord);
        //注册成功保存信息
        SaveRegisterData();

        return true;
    }

    //检查用户名和密码是否合法
    public bool CheckInfo(string userName, string passWord)
    {
        if( registerData.registerInfo.ContainsKey(userName) )
        {
            if( registerData.registerInfo[userName] == passWord )
            {
                return true;
            }
        }
        return false;
    }


    //登录面板 记录的玩家数据
    private LoginData loginData;
    //为了安全 提供一个 只能得不能改的 属性给外部 获取 登录相关的信息
    public LoginData LoginData => loginData;

    //提供给外部 存储数据的方法
    public void SaveLoginData()
    {
        XmlDataMgr.Instance.SaveData(loginData, "LoginData");
    }


    //登录管理器中 注册成功后 应该把上一次别人登录的 id清空
    public void ClearLoginData()
    {
        loginData.frontServerID = 0;
    }
}

ServerPanel

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

public class ServerPanel : BasePanel<ServerPanel>
{
    //服务器信息
    public UILabel labInfo;
    //换区按钮
    public UIButton btnChange;
    //开始游戏按钮
    public UIButton btnBegin;
    //返回按钮
    public UIButton btnBack;

    public override void Init()
    {
        //服务器面板换区按钮监听
        btnChange.onClick.Add(new EventDelegate(()=> {
            //打开服务区选择面板
            ChooseServerPanel.Instance.ShowMe();

            //隐藏自己
            HideMe();
        }));

        //服务器面板进入游戏按钮监听
        btnBegin.onClick.Add(new EventDelegate(()=> {

            //真正进入游戏了 那么久再存储一次登录数据 把服务器ID存下来
            LoginMgr.Instance.SaveLoginData();

            //进去游戏 场景切换
            SceneManager.LoadScene("GameScene");
        }));

        btnBack.onClick.Add(new EventDelegate(() => {

            //返回登录面板
            LoginPanel.Instance.ShowMe();

            HideMe();
        }));

        //一开始隐藏自己
        HideMe();
    }

    //服务器面板显示方法
    public override void ShowMe()
    {
        base.ShowMe();
        //之后再这里更新 lab显示的服务器信息即可
        //根据玩家上一次的服务器ID 从登录管理器中得到数据 进行更新
        int id = LoginMgr.Instance.LoginData.frontServerID;
        Server info = LoginMgr.Instance.ServerInfo.serverDic[id];
        labInfo.text = info.name;
    }


}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏