仿LOL项目开发第二天

仿LOL项目开发第二天

                                      by草帽

接着上节来讲,上节更新还没开始写代码逻辑,今天我们补充完整。

我们找到VersionManager脚本里面的CheckVersion方法:

首先我们想到检测版本,需要从服务器下载信息,那么肯定要提前检测下网络是否良好,并比较版本信息。

所以,我们写个BeforeCheck方法:

    /// <summary>
    /// 检测网络状况并对照版本信息是否一致
    /// </summary>
    /// <param name="AsynResult">版本信息是否一致的处理委托</param>
    /// <param name="OnError">错误处理委托</param>
    public void BeforeCheck(Action<bool> AsynResult, Action OnError)
    {
        CheckTimeout checkTimeout = new CheckTimeout();
        checkTimeout.AsynIsNetworkTimeout((success) =>
        {
            //如果网络良好,开始下载服务器版本xml
            if (success)
            {

            }
            else
            {
                if (OnError != null)
                {
                    OnError();
                }
            }
        });
    }

在写网络良好判断的带参匿名委托之前,我们先来思考一个问题,网络良好接下来需要做什么?

就是下载服务端的版本信息,但是得需要一个url地址来访问?

那么这个服务端版本信息的URL在哪里?难道要把绝对的URl定死的写入到代码中。

假如我以后服务器的URL换了呢?那么就要重新改写代码。这种方案否决,不可取。

所以呢,这个服务器的URL应该得写入到配置文件中,从服务器那边下载。

非常nice,之前我们不是写个一个SystemConfig,我们就在里面初始化服务器的URL。

所以SystemConfig需要一个Init()的初始方法。

初始配置文件分为两类:

1.从服务器那边获取的配置信息,比如版本信息,游戏服务器各个大区的信息

2.本地配置信息,比如声音大小,屏幕分辨率等等

首先,先来加载服务器相关的配置信息,与服务器相关的,我们需要分类:所以写个CfgInfo类:

    public class CfgInfo
    {
        public int id { get; set; }
        public string name { get; set; }
        public string url { get; set; }
    }

比如版本信息类id=0,游戏服务器大区类id=1,然后分别对应着不同的url,这样我们管理起来就清晰多了。

那么这个CfgInfo信息是哪里来的,肯定也需要访问服务器那边的url获取,所以呢,我们在Resources文件夹下面创建一个txt,里面写着这个Url,然后访问URl,读取里面的内容初始化所有的CfgInfo类存到列表中List<CfgInfo>,最后还要把Url文本保存在持久文件夹下,以便以后使用,OK分析完之后。

在SystemConfig类下创建常量:CfgPath持久路径

public readonly static string CfgPath = Application.persistentDataPath + "/cfg.xml";

然后我们在SystemConfig里面创建LoadCfgInfo()方法,在Init()里面调用:

private static bool LoadCfgInfo()
    {
        string cfgStr = null;
        //如果存在持久路径,就直接加载文本
        if (File.Exists(CfgPath))
        {
            cfgStr = UnityTools.LoadFileText(CfgPath);
        }
        else
        {
            //从Resources从加载配置文本
            TextAsset cfgUrl = Resources.Load("cfg") as TextAsset;
            if (cfgUrl)
            {
                //从网页上下载与服务端有关的所有配置xml字符串
                cfgStr = DownloadMgr.Instance.DownLoadHtml(cfgUrl.text);
            }
            else
            {
                cfgStr = null;
            }
        }
        //加载xml内容为列表类
        CfgInfoList = LoadXMLText<CfgInfo>(cfgStr);
        return true;
    }

 

LoadXMLText<T>(string xmlText):

    /// <summary>
    /// 将xml转换成list<T>列表类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="xmlText"></param>
    /// <returns></returns>
    private static List<T> LoadXMLText<T>(string xmlText)
    {
        List<T> list = new List<T>();
        try
        {
            if (string.IsNullOrEmpty(xmlText))
            {
                return list;
            }
            Type type = typeof(T);
            XmlDocument doc = XmlResAdapter.GetXmlDocument(xmlText);
            Dictionary<int,Dictionary<string,string>> map = XmlResAdapter.LoadXMLToMap(doc,xmlText);
            var props = type.GetProperties(~System.Reflection.BindingFlags.Static);
            foreach (var item in map)
            {
                var obj = type.GetConstructor(Type.EmptyTypes).Invoke(null);
                foreach (var prop in props)
                {
                    if (prop.Name == "id")
                    {
                        prop.SetValue(obj,item.Key,null);
                    }
                    else
                    {
                        try
                        {
                            if (item.Value.ContainsKey(prop.Name))
                            {
                                var value = UnityTools.GetValue(item.Value[prop.Name],prop.PropertyType);
                                prop.SetValue(obj,value,null);
                            }
                        }
                        catch(Exception e)
                        {
                            Debug.LogException(e);
                        }
                    }
                }
                list.Add((T)obj);
            }
        }
        catch(Exception e)
        {
            Debug.LogException(e);
        }
        return list;
    }

  

XmlResAdapter.LoadXMLToMap():

        /// <summary>
        /// 将xml内容转换成map
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static Dictionary<int, Dictionary<string, string>> LoadXMLToMap(XmlDocument doc, string content)
        {
            var result = new Dictionary<int, Dictionary<string, string>>();
            int index = 0;
            foreach (XmlNode item in doc.SelectSingleNode("root").ChildNodes)
            {
                index++;
                if (item.ChildNodes == null || item.ChildNodes.Count == 0)
                {
                    continue;
                }
                int key = int.Parse(item.ChildNodes[0].InnerText);
                if (result.ContainsKey(key))
                {
                    continue;
                }
                var children = new Dictionary<string, string>();
                result.Add(key, children);
                for (int i = 1; i < item.ChildNodes.Count; i++)
                {
                    XmlNode node = item.ChildNodes[i];
                    string tag = null;
                    if (node.Name.Length < 3)
                    {
                        tag = node.Name;
                    }
                    else
                    {
                        string tagTial = node.Name.Substring(node.Name.Length - 2, 2);
                        if (tagTial == "_i" || tagTial == "_s" || tagTial == "_f" || tagTial == "_l" || tagTial == "_k" || tagTial == "_m")
                        {
                            tag = node.Name.Substring(0, node.Name.Length - 2);
                        }
                        else
                        {
                            tag = node.Name;
                        }
                    }
                    if (node != null && !children.ContainsKey(tag))
                    {
                        if (string.IsNullOrEmpty(node.InnerText))
                        {
                            children.Add(tag, "");
                        }
                        else
                        {
                            children.Add(tag, node.InnerText.Trim());
                        }
                    }
                }
            }
            return result;
        }

  

所以这里我们就需要用到第一节提到的准备工具:WampServer集成的网页开发工具:

因为这里我们需要涉及到访问服务器的url,所以我们自己架设一个http服务器站点。

打开WampServer,找到www目录

然后新建一个文件夹,命名为LOLGameDemo

在这个文件夹下面新建一个xml,命名为Cfg.xml

然后回到Unity的Resources文件下面新建一个txt,也命名为Cfg.txt。

编辑txt里面的内容:


然后编辑Cfg.xml的内容:

然后在LOLGameDemo文件夹下,新创建一个ServerVersion.xml文本,为服务器的版本信息:

OK,大功告成。接着我们回到VersionManager里面的BeforeCheck方法里面:

我们要获取到服务器版本的url,所以得回到SystemConfig编写一个GetCfgInfoByName()方法或者GetCfgInfoById()的接口。

GetCfgInfoByName():

    /// <summary>
    /// 根据名字取得服务端配置信息Url
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public static string GetCfgInfoUrlByName(string name)
    {
        string result = "";
        foreach (var item in CfgInfoList)
        {
            if (item.name == name)
            {
                result = item.url;
                break;
            }
        }
        return result;
    }

GetCfgInfoById():

    /// <summary>
    /// 根据id取得服务端配置信息Url
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public static string GetCfgInfoUrlById(int id)
    {
        string result = "";
        foreach (var item in CfgInfoList)
        {
            if (item.id == id)
            {
                result = item.url;
                break;
            }
        }
        return result;
    }

因为我们下载的服务器的版本文本也要保存在持久文件目录,所以:

public readonly static string ServerVersionPath = Application.persistentDataPath + "/serverVersion.xml";

还有之前我们只是初始化本地版本信息类的实例,所以现在我们在VersionManager创建一个服务端的版本信息类:

    /// <summary>
    /// 本地版本信息属性
    /// </summary>
    public VersionManagerInfo LocalVersion { get; private set; }
    /// <summary>
    /// 服务版本信息属性
    /// </summary>
    public VersionManagerInfo ServerVersion { get; private set; }

然后再次回到BeforeCheck方法里面,终于回来了!0.0!

public void BeforeCheck(Action<bool> AsynResult, Action OnError)
    {
        CheckTimeout checkTimeout = new CheckTimeout();
        checkTimeout.AsynIsNetworkTimeout((success) =>
        {
            //如果网络良好,开始下载服务器版本xml
            if (success)
            {
                DownloadMgr.Instance.AsynDownLoadHtml(SystemConfig.GetCfgInfoUrlByName("version"),
                (serverVersion) =>
                {
                    //如果本地存在服务端的版本信息文本,覆盖下载的服务器文本
                    if (File.Exists(SystemConfig.ServerVersionPath))
                    {
                        serverVersion = UnityTools.LoadFileText(SystemConfig.ServerVersionPath);
                    }
                    //将文本转换成版本信息类
                    ServerVersion = GetVersionInXml(serverVersion);            //开始进行比较版本号
                    bool programVersion = ServerVersion.ProgramVersionCodeInfo.Compare(LocalVersion.ProgramVersionCodeInfo) > 0;
                    bool resourceVersion = ServerVersion.ResourceVersionCodeInfo.Compare(LocalVersion.ResourceVersionCodeInfo) > 0;
                    //执行是否更新的委托
                    AsynResult(programVersion || resourceVersion);
                },OnError);
            }
            else
            {
                if (OnError != null)
                {
                    OnError();
                }
            }
        });
    }
时间: 2024-12-06 17:55:43

仿LOL项目开发第二天的相关文章

仿LOL项目开发第三天

仿LOL项目开发第二天 by草帽 昨个我们已经实现了下载功能,但是发现没有,下载的包是压缩的,没有解压开,那么Unity是识别不了的. 所以今个我们来讲讲如何实现解压文件. 还记得吗,我们在DownloadTask里面添加了一个完成下载后的一个解压委托,我们还没有实现,那么,我们就去解决他. 回到VersionManager的DownloadPackageList方法里面,在OnDownloadFinished委托里面,添加解压缩的代码. 之前讲过类的单一职责,所以不可能在VersionMana

仿LOL项目开发第四天

---恢复内容开始--- 仿LOL项目开发第四天 by草帽 上节讲了几乎所有的更新版本的逻辑,那么这节课我们来补充界面框架的搭建的讲解. 我们知道游戏中的每个界面都有自己的一个类型:比如登陆界面,创建角色界面. 既然有这么多的界面,所以呢,我们创建一个单例的UI管理器:WindowManager.cs,然后里面创建一个字典来存所有类型的界面: using UnityEngine; using System.Collections.Generic; using Game; using Game.C

仿LOL项目开发第六天

仿LOL项目开发第六天 by草帽 OK,因为更新模块已经处理好了,接着开始登陆的编写.那么我们就需要状态机的管理. 所谓状态机就是在哪个状态执行那个状态的代码逻辑: 那么我们开始编写GameStateManager来管理: 我们先在DefineCommon里面定义游戏状态类型: /// <summary> /// 游戏状态 /// </summary> public enum GameStateType { GS_Continue,//中间状态,也就是说介于两个状态转换的中间状态

团队项目开发第二次冲刺阶段第五天

昨天做了什么?为我的奖状部分和排行榜部分的listView进行了美化,而显示的内容数据库里并没有添加,搞了一下连数据库和实现显示头像的问题.今天准备做什么?今天还是主要解决连数据库和实现显示头像的问题,这个问题看起来挺复杂,找了很多方法但是感觉并不适用.遇到了哪些问题?因为我们的主体框架正在修改,我现在做的工作是脱离任务,没法进行测试,而且也没有找到很好的方法,头像问题比较难实现了.

Java项目开发第二天

相对来说今天还是轻松了挺多的,好了,刚刚跑完步,今天心情不错,直接进入主题,就不废话了. (PS:室友都去准备迎新了,老大也是,还好都将课本留给我了,可以好好的看看书了,好好学习,天天向上.) 图形用户界面基础: GUI API包含的类可以分为三组:组件类,容器类,辅助类 用instanceof判断就知道有JButton,JComponent,Container,Component,Object等等都是JButton对象的返回值为true: 容器类和GUI辅助类 javax.swing.JFra

团队项目开发第二次冲刺阶段第三天

昨天做了什么?制作软件logo,一直在犹豫不决,拿不定主意,而且因为事情比较多,考试临近,花费的时间比较少,效率低.今天准备做什么?我也看到了老师的评价,的确效率很低,也不是很有价值,因为我自己的模块差不多完成了,因为整体的结构又要修改做大的改动,所以我的模块还暂时加不上去,后续的工作还不能进行,只能做些美工.今天把logo完成,对我的模块进行了简单的美化,并且为其它界面控件找了些不错的素材与效果,希望以后可以用到.遇到了哪些问题?我觉得对于我来说最大的问题是listview接入数据库,以及显示

团队项目开发第二次冲刺阶段第一天

1.昨天干了什么? 总结了一下我们下一个冲刺阶段的任务,为上一期的成果找出了很多瑕疵和待完善的功能. 2.今天准备干什么?, 我们的logo不太好看,作为组里唯一的女生,自然就选择了这项任务,不过photoshop用的不是太好,还需要学习i 3.遇到什么困难? 额(-?-;),觉得怎么做都不好看,实在不知道该做成什么样子既能体现铁大又能体现封神榜又能展现出它的功能...着实伤脑筋.

阅读《31天学会CRM项目开发》 第二天

http://www.huiyaosoft.com/31crmad.aspx?qq=914261631     ——参与送书的活动地址 首先很感谢作者的送书.说实在第一次收到签名的书籍,感受还很特别哟.嘿嘿! 首先介绍下这本书吧 一套CRM项目系统(CRM:客户关系管理系统),5个项目开发的必须环节,31个拓展实例,38个演示示例. 第二天 CRM是什么? CRM客户关系管理系统. 是指企业用CRM技术来管理与客户之间的关系.他是指用计算机自动化分析销售,市场营销,客户服务以及应用等流程的管理软

第八章 企业项目开发--分布式缓存memcached

注意:本节代码基于<第七章 企业项目开发--本地缓存guava cache> 1.本地缓存的问题 本地缓存速度一开始高于分布式缓存,但是随着其缓存数量的增加,所占内存越来越大,系统运行内存越来越小,最后系统会被拖慢(这一点与第二点联系起来) 本地缓存存于本机,其缓存数量与大小受本机内存大小限制 本地缓存存于本机,其他机器的访问不到这样的缓存 解决方案:分布式缓存 Jboss cache:缓存还存于本机,但是会同步更新到其他机器(解决了第三个问题,解决不了第一和第二个问题),如果缓存机器数量很多