lol是用什么编程用c语言编写计算器的编写的

大型的单机游戏(比如《使命召唤》等)是用什么样计算机语言开发的?怎样知道FCMDSFC - noYes游戏王国
欢迎来到noYes游戏王国
大型的单机游戏(比如《使命召唤》等)是用什么样计算机语言开发的?怎样知道FCMDSFC
发表时间: 05:50:02浏览:12次
在上一篇文章中,小编为您详细介绍了关于《》相关知识。本篇中小编将再为您讲解标题大型的单机游戏(比如《使命召唤》等)是用什么样计算机语言开发的?怎样知道FCMDSFC。
之前本站也有不少关于类似内容介绍:1.2.3.
业余爱好者,个人的了解比较有限,希望对你有所帮助。
①般的大型游戏开发绝不是用某种语言这么单纯的问题。
首先①般的游戏开发架构(Windows平台)从底到顶①般是Direct X(TM)——游戏引擎——游戏。
Direct X(TM)相当于所有显卡的①个统①接口,为游戏提供①个利用硬件渲染的编程模型,但Direct X(TM)接口为了追求高性能功能非常单纯和松散,不利于游戏的高效开发。此时就需要根据游戏特点对其进行适当的取舍和封装,实现①组更高抽象的游戏开发接口和框架,可以理解成游戏引擎中的图形引擎。这部分的开发①般使用的语言是C/C++和少量的汇编语言。
至于游戏引擎是①个非常复杂的功能聚合体,所有的游戏开发工作都是在之上进行的。包括图形引擎,音频引擎,碰撞引擎,艺术资源管理,脚本引擎等等。到此为止几乎还没有涉及到你所说的游戏开发。
首先在图形渲染方面,例如光照阴影处理等等,现代显卡①般是通过可编程着色器实现对图形效果的控制,所采用的编程语言①般是①些着色器语言,例如Direct X(TM)采用的HLSL,OpenGL使用的GLSL等等,语法类似C语言,游戏执行时被编译加载到显卡上,在实现硬件渲染速度的同时又实现了软件编程的灵活性。
大型游戏开发的绝大部分工作其实都是在编写游戏脚本,脚本是大型游戏得以如此高速开发和发布的主要原因。脚本化的开发让游戏开发摆脱了硬编码的种种弊端,让游戏内容可以轻易的修改和调试。游戏故事如何进行,各种事件如何触发,何时该播放哪些声音或动画,如何使用艺术团队创作的资源,这些都是在脚本中编写的,可以说引擎决定了游戏能做什么,而脚本才真正决定了游戏做了什么。①些著名的引擎如虚幻系列都有自己独特的脚本语言,其他①些引擎可能会采用①些第③方的脚本语言,比如比较流行的Lua。所以开发①个新游戏最简单的情形就是沿用之前的引擎,创作艺术资源,然后编写脚本将其组织成①个游戏,几乎不需要什么底层的编程语言。
开发环境方面,游戏团队内部可能会使用①些开发和设计工具对资源进行处理,可以理解成游戏引擎的IDE,这部分因为是内部工具,而且可能需要经常修改所以①般采用比较高效的开发平台和语言,比如暴雪就是部分使用.NET和C#进行①些内部工具的开发。
至于引擎核心的开发,Windows平台比较流行的方法是使用最新版本的Visual Studio,显卡厂商如NVIDIA也会为VS开发①些插件来简化显卡编程和调试。
所以①个大型游戏的开发需要庞大的团队使用各种各样的语言和工具来完成。总结①下主要有C/C++,汇编语言,着色器语言,脚本语言,高效的开发语言C#或Java。
其他的平台不熟,我这里就说下FC吧。
首先的问题是:怎么定义CPU使用率呢?在带有操作系统的计算机环境下我们①般把某个进程的CPU使用率定义为①段时间内进程运行所消耗的CPU时间的占比。
然而FC游戏运行既没有操作系统可以负责托管空闲CPU时间片,CPU也不支持睡眠功能,那如果游戏①个tick的音画渲染和逻辑处理完了还没到①帧时间怎么办呢?当然是不停地执行无条件跳转耗时间直到下①帧的中断到来(有的游戏是纯粹耗时间,有些游戏会拿这段时间做累加器用来当伪随机数发生器),所以如果以通常的CPU使用率来定义的话那FC游戏的CPU使用率就肯定是①(0)(0)%了。
虽然CPU是被①(0)(0)%占用,但还是可以分「有效CPU使用」和「无效CPU使用」。运行游戏主逻辑的代码都是属于有效使用,而①个tick跑完后拖时间的死循环就可以认为是无效使用。我们可以将有效CPU使用占比视为FC游戏的CPU的使用率。
那么如何测定某①帧时间内CPU的使用率呢?如果在开发的时候①个简单的方法就是把tick跑完之后拖时间的代码改成①个累加器,使得值的增长速度和指令消耗的时钟数同步,这样通过这个计数就可以得知每帧的无效时钟周期数,就能知道CPU使用率了。
不过这里我打算利用virtuanes模拟器带上点简单的hack来估计下现有游戏的CPU使用率,就以美版「魂斗罗」为例好了。
我的做法是,把无效CPU使用的代码替换成可以提示当前PPU渲染画面已经渲染到了哪①行了的代码。其实这个实现还比较简单,PPU寄存器(0)x②(0)(0)①的bit (0)是控制当前渲染是彩色渲染还是黑白渲染,所以只要把tick完了最后那个替换成设置黑白渲染模式的代码就行。由于PPU渲染画面是从上到下逐行渲染的,只要看下画面上从哪行开始往下的画面都成了黑白色就知道① tick跑完之后PPU工作到哪了。
那和CPU是什么关系呢?这个就要知道PPU的工作时序了。
以NTSC制式为例,详细的时序可以参见
这里就粗略的描述下好了:VBlank NMI中断信号到来(游戏主逻辑开始新tick运行),PPU先是处于「睡眠」状态,持续时间大约占①帧的⑧%,然后剩下约⑨②%时间就是在逐行渲染了。这里为了简便就不考虑pre render和post render line了。
那么就可知,如果按前述测量方法,某帧的画面全部变成灰色,那么可以认为该帧CPU使用率小于⑧%。如果画面的彩色部分占比为x%,那么可以认为该帧的CPU使用率大约是(⑧ + x * (0).⑨②)%。
利用virtuanes debug版运行美版魂斗罗,利用debug找到tick后拖时间的代码(看起来像是个随机数发生器)
然后用普通版本virtuanes打开游戏(debug版CPU频率被人为调快了),按P暂停模拟器,打开内存查看器,找到(0)xC(0)⑤⑦处直接修改RAM,把A⑤ ①A ⑥⑤ ③④ ⑧⑤ ③④改成A⑨ ①F ⑧D (0)① ②(0) EA,修改后的②进制码对应的汇编是:
LDA $#①F C(0)⑤⑨:
NOPC(0)⑤C:
⑧D (0)① ②(0)
STA $②(0)(0)①C(0)⑤D:
④C ⑤⑦ C(0)
JMP $C(0)⑤⑦
看下效果吧!(需要在设置里打开②④(0)线渲染)
游戏开始时大概就在这个位置(会有上下波动),彩色部分占②⑤%,可推算出此帧期间CPU使用率为大约③①%。
再往后玩,发现第①关过桥到第①个炮台这里CPU消耗很大,已经是⑨(0)%左右了。
利用单帧步进的方式看下S枪开枪时候的CPU处理消耗吧:开枪的那①帧CPU消耗高了②⑤%左右,也就是说初始化S弹的⑤颗子弹要花费⑦(0)(0)(0)多个CPU周期。
编后语:关于《大型的单机游戏(比如《使命召唤》等)是用什么样计算机语言开发的?怎样知道FCMDSFC》关于知识就介绍到这里,希望本站内容能让您有所收获,如有疑问可跟帖留言,值班小编第一时间回复。
下一篇内容是有关《》,感兴趣的同学可以点击进去看看。
英雄联盟幸运召唤师活动根据以前推出的时间来判断,lol幸运召唤师上线时间①般会在每个月①⑥号-①⑧号开始,月底结束,而这个月①⑥-①⑧号已经过去了,为毛还没有出呢?难道TX这个月已经不打算出幸运召唤师的活动了?还是在密谋着①个更大的活动呢?(马上④周年了)这①切我们都不得而知了,具体是什么情况,还是要看官方安排了,作为玩家
● ● ● ● ● ● ● ● ● ● ● ● ● ●
类型:策略
1001万+次下载
类型:休闲
1001万+次下载
类型:休闲
1001万+次下载
类型:射击
1001万+次下载
类型:经营
1001万+次下载
类型:益智
1001万+次下载
类型:冒险
1001万+次下载
类型:休闲
1001万+次下载
类型:休闲
1001万+次下载
类型:休闲
1001万+次下载你最深爱的编程语言其实很烂【吐槽/慎入】 - 编程语言 - ITeye资讯
相关知识库:
我最近写了几篇比较严肃的博客,是关于一些沮丧的事情,结果我开始有些忧郁。很严重。所以,我想应该说些比较轻松的事情。我要做的就是数落大家最喜欢的编程语言。你会问我为什么,为什么要搞这种恶作剧?亲爱的朋友,我能想出三种理由。
我无聊,没有更好的事情去做。
我自命不凡,坐在家里,深知即使我侮辱了你编程最喜欢用的语言,你也拿我没辙。除非你能发明出这样的东西:
我忘了第三个理由是什么,但我敢肯定,那一定是一个非常有趣的理由。
好了,不再浪费口舌,你最深爱的编程语言其实很烂。
哦,你听说学习C语言是必须的,因为大师Joel Spolsky这样告诉你的。他说了这种语言是最优秀的,最能体现编程语言的本质,等等等等。然而,当你花了20个小时调试一个弱者的bug,却发现是某个鸟人忘了检查存储的指针。请告诉我,最有本质特色的编程语言有多好?或者花10天时间在百万个函数中找出哪一个没有释放内存。哦,没错,我的老弟,你简直爱死C语言了。
让我来告诉你用C语言编程时的感觉:把你的手握成拳头。对,握紧。现在使劲揍自己。恭喜,你现在就是一名C语言程序员了。
让我来给你开开窍。你喜欢上一种囊括所有C语言的丑陋的语言,而且在此之上还增加了自己的丑陋。就如狗屎上再堆一层狗屎,每过几年就会增加一层。
10行C++代码的编译要用去45分钟,而抛出的错误信息比《指环王》戒指上的那一行字还要扼要。
“甘道夫17年后回来。‘我一直在研究大量的古文献,’他说。‘答案很明显。这是一个模板错误。但我不会告诉你,因为这是一种很垃圾的语言,这种错误不会重现’’”.
等一下,你在说C++11吗? 这就是它:
Hi,你好!我需要有人写超级复杂而且超级冗余的代码。我还希望我的虚拟机在打了最新的安全补丁后每隔一天崩溃一次。对于Windows程序,我需要无论在什么操作系统上都显示一样的屎难看。你说你能帮助我?太好了!
让我来揭穿你。你不够男人,没法学C++,于是你不得不接受这个C++和Java的私生子。去写你的Windows程序吧,你这个懦夫。你不知道所有的酷孩子都在用Linux吗?
5. Visual Basic
像这样一种既能阻止犯罪又能抓捕凶手的编程语言,我无言以对。()
6. Lisp, Haskell以及其它函数式编程语言
所有的这些语言,没有一个能有资格称得上所谓的数学上的优雅的函数式编程语言。至少其它类型的语言解决过真正的问题。而Lisp/Haskell之流都活在一个幻想世界——带着墨镜,喝着美酒,写着优雅的代码。他们永远都拿那些卡通式例子给人看。“你能写出这么纠结的代码例子吗?Haskell就是比C语言好。”你说的很对,老爷爷。
还有,阅读《计算机程序的构造和解释》和其它像这样的大部头计算机书籍没有提高我的编程水平。即使阅读《格雷的五十道阴影(50 shades of grey)》这样的色 情小说或任何吸血鬼爱情小说都比你看Scheme和Haskell书籍要学到更多的编程知识。
7. Delphi/Pascal
你看这篇博客需要有领导的批准吗?Python就像一种编程语言宗教。所有的东西都要用它开发——先知这样说。否则我们都冷眼看你。
瞧瞧,这是邪教,却假装是一种编程语言。
看看我!我是那种很酷的人的编程语言。买一杯咖啡,在星巴克坐8个小时,上着免费的wifi。大声的谈论着他们有多酷。
所有他们说的话的主旨就是友好的做程序员。Ruby主要是用Rails的人群使用,他们很多根本不懂编程。嗨,ruby们!闭嘴少说一分钟行不行,让其它人也说几句。
Dudeyouaresuchamessylanguage,Isometimeswonderhowanyonewritesanythingwithyou.Ireallycan'tunderstand anycode.
你为什么会在这里?你是从让所有Wordpress网站崩溃的事情中找到了一点空闲时间?你不是还有另外一个安全补丁要更新吗?如果你还想让代码写的更乱,相信Perl语言能帮你。
12. Javascript
如果你认为JavaScript是一种编程语言,那估计你认为HTML也是一种编程语言。去写你的HTML代码吧,孩子。
13. 任何在这里没有提到的编程语言
你的编程语言如此的烂,我都不屑去写它。
14. LolCode 和 Brainfu*k
好啊好啊!终于有人知道如何写代码了。拍拍自己的背欣慰一下吧。
如果我还忘了什么语言,那请你在评论里糟蹋它吧。
英文原文: / 译文:
就像作者说的一样,每种语言都有硬伤呀。
逗比 哈哈哈& 太逗了
echo "我不会编程"
哈哈哈哈哈哈哈哈
&span style=&color:&&吐&#x69的很到位&/span&
真糟糕!!!
&span style="color:"&我不会编程&/span&
的闪光灯的好
java 吐槽 一点都不过瘾啊
作者很有意思!
干点实事吧。。。
挺有趣的杂文。
原作者真是够无聊的
相关资源推荐---恢复内容开始---
仿LOL项目开发第一天
                                by---草帽
                           项目源码研究群:
最近看了一个类似LOL的源码,颇有心得,所以今天呢,我们就来自己开发一个类似于LOL的游戏demo。
可能项目持续的时间会比较久,主要是现在还在上学,所以基本上是在挤出一点课余时间来写的博客。
如果项目更新慢,还请各位谅解。
这个项目呢,大家可以跟着我的步骤一起做。博客上我会尽量的详细的教大家如何制作一款商业游戏。
OK,回归正题。现在我们来做游戏的前期准备工作:
1.Unity3d---&版本5.0以上,我用的5.3.1版本
2.Eclipse----&版本随意,但是jdk的版本要1.7以上
3.php+mysql+apache,可以去网上搜下:WampServer,里面集成了这些工具。
正式开始:
1.打开Unity5,新创建一个项目,取名为LOLGameDemo:
2.创建文件夹用来存放各种资源,比如Resources,Scripts,Scenes等,然后导入插件NGUI。
这里我用的是3.9.0版本的。
3.制作一个新的场景,我们取名为Login,存放在Scenes文件目录下,为什么取名为Login,就像LOL一样,我们一打开游戏是不是就是登陆界面。可能有些童鞋会问,不是还有更新吗,没有错,我们把更新部分的代码,集成到了Login场景中。
4.编写脚本,这是我们程序的第一个脚本,第一个脚本通常来做什么?
没错就是驱动其他脚本的执行,比如检测更新,资源加载等等等等。
那么,我们在Scripts文件下创建:LOLGameDriver.cs驱动脚本,然后在Hierachy窗口创建一个空物体,取名为LOLGameDriver,来存放这个脚本。
打开编辑脚本:
由于是驱动器,在整个游戏中,肯定只需用到一个,所以我们得设计成单例。
using UnityE
using System.C
/// &summary&
/// 驱动脚本
/// &/summary&
public class LOLGameDriver : MonoBehaviour
/// &summary&
/// 静态单例属性
/// &/summary&
public static LOLGameDriver Instance
void Awake ()
//如果单例不为空,说明存在两份的单例,就删除一份
if (Instance != null)
Destroy(this.gameObject);
Instance =//初始化单例
DontDestroyOnLoad(this.gameObject);
Application.runInBackground =//可以在后台运行
Screen.sleepTimeout = SleepTimeout.NeverS//设置屏幕永远亮着
void Start ()
void Update ()
5.编写检测版本更新的情况。
在编写代码之前,我们先来制作登陆界面,不然运行的时候空白的界面显得不好看。
这里我创建了一个Temp来存放临时的Textures,因为我们界面用到的只是图集,并不是这些textures,所以制作完图集之后,就可以直接删了。
我们打开NGui的制作图集的工具,然后制作Login.altas图集,存放在新建的Altas文件夹下面:
关于登录界面的Textures,我会在文章的最后部分提供链接。
制作玩图集之后,我们开始拼凑界面。不论怎么说制作界面是最烦的时候,也是最浪费时间。
这个是我随手搭建的登陆界面:这里主要分两块
1.LoginFrame----&就是整体的框架,不包括右边有用户名输入的UI
2.Login------&这个是右边有用户名输入框的UI
为什么要分这两部分,你想想看,如果LOL游戏要更新的时候,是不是就只有背景图片,并没有用户名输入框那个UI。所以我们要独立出用户名那个UI,动态来加载他。
那么,我们就要把它制作成Prefab。
在Resources文件下,创建Guis文件目录,然后拖拽Login到文件中。
具体界面怎么制作,你们自己搞,我这里就不再详细的讲解。
OK,那么接下来,我们开始编写程序。
回到LOLGameDriver脚本内,新建一个public方法,取名为TryInit();主要是用来检测是否有网络和版本更新。
首先是网络是否可行的检测:
我们新建一个类:CheckTimeout.cs专门用来检测网络是否良好。
在写之前,我们考虑下,这个类是用来检测网络性能,而其中需要有下载功能,所以违背了类的单一职责原则,我们设计的类的时候,尽量不要让他太过于复杂。
所以处理下载功能的,我们专门写个DownloadMgr.cs来处理。
我们新建一个下载类,由于你的下载管理器也肯定是只在内存中存在一份,所以我们设计成单例:
using UnityE
using System.C
using System.N
public class DownloadMgr
private static DownloadMgr m_oI
private WebClient m_oWebC
public static DownloadMgr Instance
if (m_oInstance == null)
m_oInstance = new DownloadMgr();
return m_oI
public DownloadMgr()
this.m_oWebClient = new WebClient();
/// &summary&
/// 异步下载网页文本
/// &/summary&
/// &param name="url"&&/param&
/// &param name="AsynResult"&&/param&
/// &param name="onError"&&/param&
public void AsynDownLoadHtml(string url, Action&string& AsynResult, Action onError)
Action action = () =&
string text = DownLoadHtml(url);
if (string.IsNullOrEmpty(text))
if (onError != null)
onError();
if (AsynResult != null)
AsynResult(text);
//开始异步下载
action.BeginInvoke(null, null);
/// &summary&
/// 下载网页的文本
/// &/summary&
/// &param name="url"&&/param&
/// &returns&&/returns&
public string DownLoadHtml(string url)
return this.m_oWebClient.DownloadString(url);
catch (Exception e)
Debug.LogException(e);
return string.E
只要在CheckTImeout类里面调用DownloadMgr的AsynDownloadHtml()方法,就可以进行异步下载,然后初始化带参的委托。我们看看CheckTimeout.cs代码:
using UnityE
using System.C
/// &summary&
/// 检测网络是否超时类
/// &/summary&
public class CheckTimeout
/// &summary&
/// 是否网络超时,这里使用百度做测试
/// &/summary&
/// &param name="AsynResult"&&/param&
public void AsynIsNetworkTimeout(Action&bool& AsynResult)
TryAsynDownloadHtml("http://www.baidu.com", AsynResult);
private void TryAsynDownloadHtml(string url, Action&bool& AsynResult)
DownloadMgr.Instance.AsynDownLoadHtml(url, (text) =&
if (string.IsNullOrEmpty(text))
AsynResult(false);
AsynResult(true);
}, () =& { AsynResult(false); });
再回到LOLGameDriver脚本:在TryInit()方法里面编写代码:
public void TryInit()
//说明网络可以
if (Application.internetReachability != NetworkReachability.NotReachable)
CheckTimeout checkTimeout = new CheckTimeout();
checkTimeout.AsynIsNetworkTimeout((result) =&
//网络良好
if (result)
//开始更新检测
else //说明网络错误
//开始消息提示框,重试和退出
可能读者看到这样的代码,就是委托比较多的代码,头就很晕。其实委托很简单,你们只要记住,委托就是方法指针。用来干嘛,解耦和用的。
你看如果不用委托,是不是LOLGameDriver得注入到CheckTimeout和DownloadMrg里面充当依赖,但是委托直接把LOLGameDriver的里面的匿名委托当做方法指针传递到DownloadMrg里面执行。
OK,讲完网络监测之后,我们来讲讲版本检测更新。
我们在LOLGameDriver的网络良好的判断里面,新增一个方法:DoInit();
那么我们知道,所谓的版本更新,无非就是服务端的版本信息和客户端版本信息的对照。
那么客户端的版本信息保存在哪里?没错就是Application.persistentDataPath这个持久文件路径。
所以我们新建一个类,专门管理这些与系统有关的路径:SystemConfig.cs:
using UnityE
using System.C
/// &summary&
/// 系统参数配置
/// &/summary&
public class SystemConfig
public readonly static string VersionPath = Application.persistentDataPath + "/version.xml";
里面存放的是本地版本信息的xml文件路径:VersionPath
因为涉及到版本控制,所以我们得有个VersionManager单例来管理。
新建一个VersionManager.cs脚本:
有没有突然发现,几乎所有的管理器都是单例模式的,你我们每个管理器都需要写个的单例,那不是特别的麻烦,所以呢,这里教大家一个小技巧:继承单例。
我们写个抽象单例的父类,放在命名空间:Game下面。
using System.T
namespace Game
public class Singleton&T& where T : new()
private static T s_singleton = default(T);
private static object s_objectLock = new object();
public static T singleton
if (null == Singleton&T&.s_singleton)
Monitor.Enter(obj = Singleton&T&.s_objectLock);
if (null == Singleton&T&.s_singleton)
Singleton&T&.s_singleton = ((default(T) == null) ? Activator.CreateInstance&T&() : default(T));
Monitor.Exit(obj);
return Singleton&T&.s_
protected Singleton()
这个单例是多线程安全的。
所以我们的VersionManager就直接继承该抽象类,注意需要引用Game命名空间:
using UnityE
using System.C
public class VersionManager : Singleton&VersionManager&
OK,正式进入VersionManager代码的编写,我们先来分析一下:
1.VersionManager的初始化,主要处理事件的注册和监听。
2.VersionManager加载本地版本信息xml,封装成版本信息类VersionManagerInfo来管理。
3.检查网络情况,开始下载服务器版本信息,也封装成VersionManagerInfo类的实例来管理。
4.对比服务器和客户端版本信息,如果一致无需更新,如果不一致,则下载资源,界面显示下载进度,完成之后,解压缩到游戏文件夹内完成更新。
先是第一步初始化,因为我们还没涉及到什么事件,所以我们先写个Init()初始化方法,等以后用到再在里面写,所以写个空的Init()。
public void Init()
第二步:加载本地版本信息,因为我们的版本信息需要进行对照,所以创建一个版本信息类来管理方便点,所以创建一个VersionManagerInfo类:
public class VersionManagerInfo
/// &summary&
/// 游戏程序版本号,基本上我们不会替换游戏程序,除非非得重新下载客户端
/// &/summary&
public VersionCodeInfo ProgramVersionCodeI
/// &summary&
/// 游戏资源版本号
/// &/summary&
public VersionCodeInfo ResourceVersionCodeI
public string ProgramVersionCode
return ProgramVersionCodeInfo.ToString();
ProgramVersionCodeInfo = new VersionCodeInfo(value);
public string ResourceVersionCode
return ResourceVersionCodeInfo.ToString();
ResourceVersionCodeInfo = new VersionCodeInfo(value);
/// &summary&
/// 资源包列表
/// &/summary&
public string PackageList { }
/// &summary&
/// 资源包地址
/// &/summary&
public string PackageUrl { }
/// &summary&
/// 资源包md5码列表
/// &/summary&
public string PackageMd5List { }
/// &summary&
/// 资源包字典key=&url,value=&md5
/// &/summary&
public Dictionary&string, string& PackageMd5Dic = new Dictionary&string, string&();
public VersionManagerInfo()
ProgramVersionCodeInfo = new VersionCodeInfo("0.0.0.1");
ResourceVersionCodeInfo = new VersionCodeInfo("0.0.0.0");
PackageList = string.E
PackageUrl = string.E
VersionCodeInfo.cs:
/// &summary&
/// 版本号
/// &/summary&
public class VersionCodeInfo
/// &summary&
/// 版本号列表
/// &/summary&
private List&int& m_listCodes = new List&int&();
/// &summary&
/// 初始化版本号
/// &/summary&
/// &param name="version"&&/param&
public VersionCodeInfo(string version)
if (string.IsNullOrEmpty(version))
string[] versions = version.Split('.');
for (int i = 0; i & versions.L i++)
if (int.TryParse(versions[i], out code))
this.m_listCodes.Add(code);
Debug.LogError("版本号不是数字");
this.m_listCodes.Add(code);
/// &summary&
/// 比较版本号,自己大返回1,自己小返回-1,一样返回0
/// &/summary&
/// &param name="codeInfo"&&/param&
/// &returns&&/returns&
public int Compare(VersionCodeInfo codeInfo)
int count = this.m_listCodes.Count & codeInfo.m_listCodes.Count ? this.m_listCodes.Count : codeInfo.m_listCodes.C
for (int i = 0; i & i++)
if (this.m_listCodes[i] == codeInfo.m_listCodes[i])
return this.m_listCodes[i] & codeInfo.m_listCodes[i] ? 1 : -1;
/// &summary&
/// 重写ToString()方法,输出版本号字符串
/// &/summary&
/// &returns&&/returns&
public override string ToString()
StringBuilder sb = new StringBuilder();
foreach (var code in this.m_listCodes)
sb.AppendFormat("{0}.", code);
//移除多余出来的.号
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
ok,我们回到VersionManager中,定义一个LocalVersion属性,类型是VersionManagerInfo类型。
public VersionManagerInfo LocalVersion { }
然后在LoadLocalVersion()方法里面初始化,怎么初始化,我们需要读取version.xml里面的内容,然后初始化。因为我们程序刚开始是不存在SystemConfig.VersionPath的文件,所以呢,我们要自己写个xml文件,放在Resource下面,然后在保存到SystemConfig.VersionPath路径上去。
public void LoadLocalVersion()
//如果已经存在本地版本文件
if (File.Exists(SystemConfig.VersionPath))
LocalVersion = new VersionManagerInfo();//默认版本的初始状态0.0.0.0
TextAsset ver = Resources.Load("version") as TextA
if (ver != null)
UnityTools.SaveText(SystemConfig.VersionPath, ver.text);
所以,创建一个xml文件,命名为version.xml放在Resources根目录下面。(其实这个xml是打包的时候自动生成的,这里我简化下,先不讲打包)
&?xml version="1.0" encoding="utf-8"?&
&ProgramVersionCode&0.0.0.1&/ProgramVersionCode&
&ResourceVersionCode&0.0.0.0&/ResourceVersionCode&
&PackageList&&/PackageList&
&PackageUrl&&/PackageUrl&
&PackageMd5List&&/PackageMd5List&
这个xml标签的名字要和VersionManagerInfo类的属性名一致。
UnityTools.SaveText(SystemConfig.VersionPath, ver.text);
这个方法我抽象出来到工具类里面去,功能是将string内容保存到一个文本文件内。
     /// &summary&
/// 保存文本到指定文件路径
/// &/summary&
/// &param name="filePath"&&/param&
/// &param name="textContent"&&/param&
public static void SaveText(string filePath, string textContent)
//如果不存在该目录就创建
if (!Directory.Exists(GetDirectoryName(filePath)))
Directory.CreateDirectory(GetDirectoryName(filePath));
//如果已经存在该文件就删除
if (File.Exists(filePath))
File.Delete(filePath);
//创建文件并写入内容
using (FileStream fs = new FileStream(filePath, FileMode.Create))
using (StreamWriter sw = new StreamWriter(fs))
sw.Write(textContent);
sw.Flush();
sw.Close();
fs.Close();
/// &summary&
/// 取得该文件所在的目录文件夹
/// &/summary&
/// &param name="filePath"&&/param&
/// &returns&&/returns&
public static string GetDirectoryName(string filePath)
return filePath.Substring(0, filePath.LastIndexOf('/'));
OK,那么加载本地版本资源完成之后,进行第三步:检查网络情况,开始下载服务器版本信息
我们知道,下载服务器版本信息,肯定涉及到界面的同步,比如下载更新消息提示框,下载进度条等等。那么,如果把这些界面都放在VersionManager或者DownloadMrg类里面处理,不符合类的单一职责,也不符合mvc模式,所以呢。
之前我们讲过,用委托来处理,把界面的处理直接通过委托传递到VersionManager或者DownloadMrg类里面。
我们回到LOLGameDriver类的DoInit()方法:
public void DoInit()
VersionManager.singleton.Init();
VersionManager.singleton.LoadLocalVersion();
CheckVersion(CheckVersionFinished);
CheckVersion(Action finished):
private void CheckVersion(Action finished)
//添加一个解压文件界面提示回调
Action&bool& fileDecompress = (finish) =&
if (finish)
//正在更新本地文件,原本是界面上显示提示消息,以后再讲,这里只是打印看看
Debug.Log("正在更新本地文件");
Debug.Log("数据读取中");
Action&int, int, string& taskProgress = (total, index, fileName) =&
//正在下载更新文件
Debug.Log(string.Format("正在下载更新文件({0}/{1}:{2})", index + 1, total, fileName));
Action&int, long, long& progress = (ProgressPercentage, TotalBytesToReceive, BytesReceive) =&
//处理进度条
Debug.Log(string.Format("进度:{0}%" ,ProgressPercentage));
Action&Exception& error = (ex) =&
Debug.Log(ex);
//界面提示版本检查中
Debug.Log("版本检查中...");
VersionManager.singleton.CheckVersion(fileDecompress, taskProgress, progress, finished, error);
这里我将这些委托直接定义在方法内部,其实我们可以自己在外部定义这些方法的,其实都是一样的。
Ok,写到在运行程序试试。唉!发现有报错误:
他说Application.persistentDataPath这个方法得在主线程里面执行,也就是说我们把它放在另外一个线程里面执行了。想想,我们哪里有用到另外一个线程。哦,对了,在Donwload的时候,我们异步下载一个网页资源。
也就是这个委托出现错误,他是在另外一个线程里面执行,然后调用LOLGameDriver.TryInit()-&DoInit()-&VersionManager.singleton.LoadLocalVersion();
所以他取得Application.persistentDataPath是在
action.BeginInvoke(null, null);
线程下面执行的。那么如何解决这个问题呢?关键是这个委托放在Update,Awake,Start或者协程里面执行,且只执行一次。
对了,之前看过我博客的童鞋可以很快想到---&
我们在LOLGameDriver类下面写个Tick方法,执行时间定时器的Tick计时:
private void Tick()
TimerHeap.Tick();
然后在Awake里面,不断的重复执行这个Tick,实际上就是一个协程。
InvokeRepeating("Tick", 1, 0.02f);
然后在创建一个添加委托执行的接口,Invoke(Action action):
public static void Invoke(Action action)
TimerHeap.AddTimer(0, 0, action);
将这个委托添加到定时器里面执行,默认为0秒之后执行,无重复(0=无重复)执行。
OK,我们只需要修改一处就可以了:
&将红色代码注释,然后添加蓝色代码就ok了。运行,观察打印信息:
OK,行了,那么本节就到这里,下节继续。。。。。。
阅读(...) 评论()}

我要回帖

更多关于 lol用什么语言写的 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信