前往Shuct.Net首页

Shudepb PB反编译专家长时间以来,为业内同类软件事实上的唯一选择.细节,彰显专业.态度,决定品质.

关于反编译的搜索

小侃s&#039;Blog 网站开发_软件设计_游戏开发_信息安全_算法研究_系统漏洞_图形设计_影视动画 小侃s&#039;Blog 小侃欢迎您&#8230;&#8230; 主页WEB程序开发WIN程序开发业内新闻原创系列小侃水库小菜乐园操作系统数据库房游戏开发漏洞交流破解技术算法相关网络技术设计风暴通讯世界 [Unity3D]脚本中Start()和Awake()的区别 2014 年 3 月 4 日 / 小侃 发表于 游戏开发 / 尚无评论 Unity3D初学者经常把Awake和Start混淆。 简单说明一下,Awake在MonoBehavior创建后就立刻调用,Start将在MonoBehavior创建后在该帧Update之前,在该Monobehavior.enabled == true的情况下执行。 [javascript]? void?Awake?(){ } //初始化函数,在游戏开始时系统自动调用。一般用来创建变量之类的东西。 void?Start(){ } //初始化函数,在所有Awake函数运行完之后(一般是这样,但不一定),在所有Update函数前系统自动条用。一般用来给变量赋值。 我们通常书写的脚本,并不会定义[ExecuteInEditMode]这个Attribute,所以Awake和Start都只有在Runtime中才会执行。 例1: [javascript] public?class?Test?:?MonoBehaviour?{ ????void?Awake?()?{ ????????Debug.Log(&#8220;Awake&#8221;); ????????enabled?=?false; ????} ????void?Start?()?{ ????????Debug.Log(&#8220;Start&#8221;); ????} } 以上代码,在Awake中我们调用了enabled = false; 禁止了这个MonoBehavior的update。由于Start, Update, PostUpdate等属于runtime行为的一部分,这段代码将使Start不会被调用到。 在游戏过程中,若有另外一组代码有如下调用: [javascript] Test?test?=?go.GetComponent<Test>(); test.enabled?=?true; 这个时候,若该MonoBehavior之前并没有触发过Start函数,将会在这段代码执行后触发。 例2: player.cs [javascript]? private?Transform?handAnchor?=?null; void?Awake?()?{?handAnchor?=?transform.Find(&#8220;hand_anchor&#8221;);?} //?void?Start?()?{?handAnchor?=?transform.Find(&#8220;hand_anchor&#8221;);?} void?GetWeapon?(?GameObject?go?)?{ ????if?(?handAnchor?==?null?)?{ ????????Debug.LogError(&#8220;handAnchor?is?null&#8221;); ????????return; ????} ????go.transform.parent?=?handAnchor; } other.cs [javascript]? &#8230; GameObject?go?=?new?GameObject(&#8220;player&#8221;); player?pl?=?go.AddComponent<player>();?//?Awake?invoke?right?after?this! pl.GetWeapon(weaponGO); &#8230; 以上代码中,我们在player Awake的时候去为handAnchor赋值。如果我们将这步操作放在Start里,那么在other.cs中,当执行GetWeapon的时候就会出现handAnchor是null reference. 总结:我们尽量将其他Object的reference设置等事情放在Awake处理。然后将这些reference的Object的赋值设置放在Start()中来完成。 当MonoBehavior有定义[ExecuteInEditMode]时 当我们为MonoBehavior定义了[ExecuteInEditMode]后,我们还需要关心Awake和Start在编辑器中的执行状况。 当该MonoBehavior在编辑器中被赋于给GameObject的时候,Awake, Start 将被执行。 当Play按钮被按下游戏开始以后,Awake, Start 将被执行。 当Play按钮停止后,Awake, Start将再次被执行。 当在编辑器中打开包含有该MonoBehavior的场景的时候,Awake, Start将被执行。 值得注意的是,不要用这种方式来设定一些临时变量的存储(private, protected)。因为一旦我们触发Unity3D的代码编译,这些变量所存储的内容将被清为默认值。 下面再来看看Unity圣典中的解释。 Awake() 当一个脚本实例被载入时Awake被调用。 Awake用于在游戏开始之前初始化变量或游戏状态。在脚本整个生命周期内它仅被调用一次.Awake在所有对象被初始化之后调用,所以你可以安全的与其他对象对话或用诸如 GameObject.FindWithTag 这样的函数搜索它们。每个游戏物体上的Awke以随机的顺序被调用。因此,你应该用Awake来设置脚本间的引用,并用Start来传递信息。Awake总是在Start之前被调用。它不能用来执行协同程序。 Start() Start仅在Update函数第一次被调用前调用。Start在behaviour的生命周期中只被调用一次。它和Awake的不同是Start只在脚本实例被启用时调用。 你可以按需调整延迟初始化代码。Awake总是在Start之前执行。这允许你协调初始化顺序。 < Awake(), Start(), unity3d, 区别, 脚本 > 深入解析和破解C#的readonly只读字段及与const的区别 2014 年 2 月 28 日 / 小侃 发表于 WIN程序开发 / 尚无评论 目录 请允许我再唠叨几句const和readonly 修改readonly字段: 计策1:反间计 —— 反射修改 计策2:借刀杀人——调节字段偏移位置的结构体来修改 计策3:无中生有——使用ilasm创建强行修改语句 问题的研究: 为什么?——翻阅CLI标准:initonly修饰符 捕获MSIL的代码验证错误 总结 返回目录 请允许我再唠叨几句const和readonly readonly?关键字与?const?关键字不同。?const?字段只能在该字段的声明中初始化。?readonly?字段可以在声明或构造函数中初始化。?因此,根据所使用的构造函数,readonly?字段可能具有不同的值。?另外,const?字段为编译时常数,而?readonly?字段可用于运行时常数。 其实大家都懂的,我就不多废话,直接重点: Const: 1>必须在定义时就进行赋值,并且赋值为常量,不能赋值为变量。 2>const常量隐含是static的,所以只能用类名来进行方法. 3>常量的类型可以为简单类型,枚举类型,各种引用类型(包括string)。这里引用类型的常量,如果不是string类型,则只允许赋以null。常量的类型不能为普通的struct类型。如果要实现struct类型的保持不变的量,可以用readonly。 4>const可以修饰方法内的局部变量。 ? ReadOnly: 1>readonly域可以是各种类型。 2>readonly域可以用变量或表达式进行赋值。 3>readonly不能修饰局部变量。 4>readonly域并不隐含static性质。 5>readonly域要求定义时初始化。如果没有初始化,自动取默认值(0,false,null等)。如果要赋值,可以定义时初始化,也可以在构造方法中赋值,包括使用out及ref参数进行处理。但它最多只能被赋值一次。赋值以后,其值不能被修改。 ? 可以看出,readonly要求的只读性时考虑&#8221;运行时时只读的&#8221;,而const要求的只读性是&#8221;编译时就是常量&#8221;。 好了,下面开始修改readonly字段。 返回目录 计策1:反间计 —— 反射修改 要说什么方法不用我们另外做手脚直接了当快速轻松得修改readonly只读属性莫过于使用.NET中的正规方式,当你直接对readonly字段进行“=”赋值操作然后编译,VS肯定给你个错误拒绝编译。但是另一种动态赋值方式——反射你有没有试过呢??? 好吧或许你曾经问过某高手说readonly字段能不能被修改,他一定会回答:“笨蛋,这还用问,能修改还叫readonly吗?”。于是聪明人知道了并记住了(或许聪明人根本不会问这样的问题)。但是……一个笨的很笨的小笨他太笨了所以还是想试试,于是先用第一种直接静态赋值方式,VS编译错误。又尝试另一种运行后的动态赋值,于是他成功了! 是的,静态方式编译器不允许,但是动态赋值——反射却背叛了它,运行后用反射想怎么改就怎么改! 看下面代码: class?Program { static?readonly?object?data?=?1; static?void?Main() { Console.WriteLine(data); mod(); Console.WriteLine(data); } static?void?mod() { //得到静态的非公有字段信息 var?fieldInfo?=?typeof(Program).GetField(&#8220;data&#8221;,?BindingFlags.Static?|?BindingFlags.NonPublic); fieldInfo.SetValue(null,?&#8221;MOD&#8221;); } } 输出: 1 MOD 值被成功修改了。 返回目录 计策2:借刀杀人——调节字段偏移位置的结构体来修改 如果你经常用C#调用非托管代码的话,P/Invoke和各种Marshal操作你会很熟悉。而另一个常用到的System.Runtime.InteropServices的StructLayout和FieldOffset特性是用来定义一个显示的字段内存布局的结构体。 没人可以阻止我们把两个字段对在一个位置,然后用一个非readonly字段去彻底控制一个readonly字段!!! 代码 using?System; using?System.Runtime.InteropServices; namespace?Mgen.TTC { [StructLayout(LayoutKind.Explicit)] struct?a { [FieldOffset(0)] public?string?s; [FieldOffset(0)] public?readonly?string?READ_ONLY; //readonly字段 public?a(string?arg) { //初始化readonly字段 s?=?READ_ONLY?=?arg; } } class?Program { static?void?Main() { //此时oa的readonly字段被初始化成字符串:&#8221;常量&#8221; a?oa?=?new?a(&#8220;常量&#8221;); Console.WriteLine(oa.READ_ONLY); oa.s?=?&#8221;你被改了……&#8221;; Console.WriteLine(oa.READ_ONLY); } } } 输出: 常量 你被改了…… 很好,这里修改变量s就等价于修改常量字段:READ_ONLY。两个字段是对在同一个内存位置的,然后通过修改一个非readonly字段去间接修改一个readonly字段。 返回目录 计策3:无中生有——使用ilasm创建强行修改语句 当你使用Visual Studio(或其他C#编译器)时对readonly字段进行赋值肯定结果是编译错误。于是你很想强行通过这条语句(于是你又非常使劲得按了下Ctrl + F5,结果……),好吧C#编译器都一个样,无法去改变它,但是C#幕后的IL并非如此。接下来让我们用ilasm.exe创建一个对readonly字段进行直接赋值的程序。 ilasm的编译需要一个IL文件,这个IL文件就是文本文件,你可以自己写IL,不过这个太麻烦了,我们可以用IL反编译程序ildasm.exe来把一个托管程序集的IL代码框架先生成,然后导出,最后加入自己的代码再用ilasm编译。 首先创建一个C#控制台程序,然后加一个readonly只读字段,编译(这样做我们就不用从头开始写IL)。如下: class?Program { static?readonly?string?s?=?&#8221;hehe&#8221;; static?void?Main(string[] args) { } } 接着用ildasm.exe打开这个程序。 (ildasm在Windows SDK中,Windows SDK路径在:%PROGRAMFILES%\Microsoft SDKs\Windows) 在File菜单选择Dump(或直接按Ctrl+D)。选择OK将IL文件保存。 然后用文本编辑器打开这个IL文件,找到Main函数(可以通过查找文字:Main)。在主函数.entrypoint指令下加入下列指令: 代表4条C#语句:输出s,修改s,再输出s,Console.Read()。 (注意下面的ConsoleApplication1.Program::s代表s字段的完整命名空间,根据你的程序做适当修改) .maxstack??8 IL_0000:? ldsfld?????string?ConsoleApplication1.Program::s??????????????//s进栈 IL_0005:? call???????void?[mscorlib]System.Console::WriteLine(string)???//输出s IL_000a:? ldstr????? bytearray (AB?88?EE?4F?39?65?)?????????????????????//字符串被修改&#8221; IL_000f:? stsfld?????string?ConsoleApplication1.Program::s??????????????//将&#8221;被修改&#8221;赋值给s IL_0014:? ldsfld?????string?ConsoleApplication1.Program::s??????????????//s进栈 IL_0019:? call???????void?[mscorlib]System.Console::WriteLine(string)???//输出s IL_001e:? call?????? int32 [mscorlib]System.Console::Read()?????????????//Console.Read() IL_0023:? pop IL_0024:? ret 接下来就用ilasm.exe来编译IL文件。 (ilasm在.NET Framework安装目录下,路径:%SYSTEMROOT%\microsoft.net\framework\) 将刚才修改后的IL文件路径作为第一个参数传入ilasm.exe中,ilasm便会将IL编译成可执行文件。然后运行这个exe。 程序会输出: hehe 被修改 你可以在Reflector(或ILSpy)中打开这个程序,它的C#代码正好是C#编译器所不允许编译的结果: internal?class?Program { // Fields private?static?readonly?string?s?=?&#8221;hehe&#8221;; // Methods private?static?void?Main(string[] args) { Console.WriteLine(s); s?=?&#8221;被修改&#8221;; Console.WriteLine(s); Console.Read(); } } 返回目录 为什么?——翻阅CLI标准:initonly修饰符 注意: 下文会引用Common Language Infrastructure (CLI) 标准的内容,如果你想亲自看一下CLI标准的内容。可以在这里下载:http://www.ecma-international.org/publications/standards/Ecma-335.htm 看完了上面的东西,你一定会问为什么?为什么执行环境没有去有效得保护一个readonly字段?为什么IL允许去修改一个readonly字段而C#不可以? 让我们开始分析一个readonly字段。如下C#代码: readonly?int?i; 接下来,你应该猜到了,又开始IL了…… (汗……别抱怨怎么又得从IL上说起,我也不想这样做,其实IL也挺无奈的,人家很低调的,但总被一些人给不停得揭露出来……仿佛他们研究得很深奥似的……(我在自嘲,没说别人)) 上面代码会被编译成下面的IL: .field?private?initonly int32 i 可以看出来,readonly字段就是一个带有initonly的字段,一切的不同就在这个initonly修饰符上。 根据CLI标准(ECMA-334),第二部分:元数据(Partition II Metadata),16. 定义和引用字段(16 Defining and referencing fields),1. 字段的属性(Attributes of field),2. 字段约定属性(Field contract attributes)中对initonly修饰符的描述: initonly?marks fields which are constant after they are initialized. These fields shall only be mutated inside a constructor. If the field is a static field, then it shall be mutated only inside the type initializer of the type in which it was declared. If it is an instance field, then it shall be mutated only in one of the instance constructors of the type in which it was defined. It shall not be mutated in any other method or in any other constructor, including constructors of derived classes. [Note: The use of ldflda or ldsflda on an initonly field makes code unverifiable.? In unverifiable code, the VES need not check whether initonly fields are mutated outside the constructors. The VES need not report any errors if a method changes the value of a constant. However, such code is not valid. end note] 上面第一段就是在说readonly的用法:initonly字段在初始化后就成为常量。这种字段只能在构造函数中改变(进行赋值)。如果是静态字段,只能在当前类静态构造函数中或初始设定项。如果是非静态字段,只能在当前类的非静态构造函数中使用(或类型初始设定项),不能在其他方法或者其他构造函数中,包括派生类的构造函数。 第二段找到了重点(以Note开始)。对initonly字段使用ldflda和ldsflda会使代码无法验证。在无法通过验证的代码环境中,VES不需要检查initonly字段是否在构造函数外发生改变,VES也不需要报错如果一个方法改变了这个只读字段的值。但是,这种代码不是合法的。 其中VES(Virtual Execution System):虚拟执行系统是指代码的运行环境,而微软的CLI执行就是CLR。 IL指令:ldflda(ldsflda用于静态字段)用于将字段的地址进栈。当使用ref/out关键字时,或者调用值类型的成员时,CLR都会把相应对象的地址压入栈中。(其实上面提到ldflda/ldsflda是指去修改readonly字段,所以不一定只限于ldflda/ldsflda,当然也没准其他IL指令会间接用到ldflda/ldsflda) OK,那么其实CLI标准没有强制要求执行环境必须要确保readonly只读字段必须遵守行为准则,只要readonly字段被非法修改,代码将会无法验证(unverifiable)。下面的问题就是无法验证的代码又是一个什么概念? 返回目录 捕获MSIL的代码验证错误 当MSIL被JIT编译时,如果程序集没有被赋予跳过代码验证的权限时,那么代码必须要通过代码验证过程,代码验证直接确保了程序的类型安全,使得对象可以绝对隔离并且免受恶意破坏,代码验证所要做的是如下具体3点: 对类型的引用与被引用的类型严格兼容。 在对象上只调用正确定义的操作。 标识与声称的要求一致。 (强烈建议阅读MSDN &#8211; 托管执行过程 &#8211; 将 MSIL 编译为本机代码 &#8211; 代码验证(http://msdn.microsoft.com/zh-cn/library/k5532s8a.aspx)) 上面提到的“跳过代码验证的权限”就是SecurityPermissionFlag.SkipVerification枚举值,而本机运行的.NET程序集默认是被给予全部权限的,因此会包含这个权限。IL代码验证是不发生的。接下来要做的就是通过创建一个没有“跳过代码验证的”应用程序域,在这个应用程序域中运行上面用IL创建的那个修改只读字段的程序集,看看会发生什么情况。 创建另一个控制台应用程序(最好把刚才的IL编译的修改只读字段的程序拷贝到此程序的编译目录下,这样可以用相对路径),然后创建一个应用程序域,并执行刚才的程序集: static?void?Main() { //创建一个没有跳过代码验证权限的应用程序域 var?appdomain?=?CreateSandbox(); //testApp.exe是刚才用IL编译的修改readonly只读字段的程序的路径 appdomain.ExecuteAssembly(&#8220;testApp.exe&#8221;); } static?AppDomain?CreateSandbox() { //初始化空的权限集 var?pset?=?new?PermissionSet(PermissionState.None); //添加Execution(执行)安全权限,没有此权限代码不会执行 pset.AddPermission(new?SecurityPermission(SecurityPermissionFlag.Execution)); //添加其他权限 pset.AddPermission(new?FileIOPermission(PermissionState.Unrestricted)); pset.AddPermission(new?UIPermission(PermissionState.Unrestricted)); //必须设置AppDomainSetup.ApplicationBase,否则无法成功创建应用程序域 var?adSetup?=?new?AppDomainSetup(); adSetup.ApplicationBase?=?AppDomain.CurrentDomain.SetupInformation.ApplicationBase; var?domain?=?AppDomain.CreateDomain(&#8220;新的AppDomain&#8221;, null, adSetup, pset); return?domain; } 运行结果:有异常抛出。很好,这正是我们想要的结果: Unhandled Exception: System.Security.VerificationException: Operation could dest abilize the runtime. at ConsoleApplication1()????? //用IL编译的程序的主函数 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args ) at System.AppDomain.ExecuteAssembly(String assemblyFile, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile) at System.AppDomain.ExecuteAssembly(String assemblyFile) at Mgen.TTC.Program.Main()??? //当前程序的主函数 可以看到System.Security.VerificationException异常被抛出。”operation could destabilize the runtime”:指操作可能使运行时刻不稳定。因为这个用IL编译的程序集包含上面提到过的“无法验证”的代码,而当前执行的应用程序域又没有被给予“跳过代码验证的安全权限”,因此代码验证此刻会发生,当程序集运行时,JIT边编译边进行代码验证,而觉察到这个“修改只读属性”的语句,它打破了代码验证所强制的运行时刻类型安全,显然破坏了运行时刻稳定性,接着马上抛出VerificationException异常,程序集执行失败。 如果你把上面的应用程序域的限制权限改成全部权限: var?pset?=?new?PermissionSet(PermissionState.Unrestricted); 重新运行一下程序,这次没有任何异常抛出,另一个程序集的只读字段会继续被修改并输出正确结果。 hehe 被修改 返回目录 总结 如果你仔细看了文章,那么“总结”对你来意义不大,因为你肯定已经自己理解了。当然如果你没时间全看完,总结告诉你的是(请从上往下看): readonly对象本质上不是常量,是字段。 标准(CLI标准)没有规定readonly字段不能被修改。 因为标准不强求,更何况readonly对象是字段,所以IL和反射都可以修改它。 当然编译器还是要尽量阻止它被修改(如果编译器都允许它被修改,那readonly这个关键字还有什么用?) 一旦readonly字段被修改了,该代码就属于无法验证代码。 MSIL在被JIT编译时会验证代码,如果遇到无法验证代码会抛出异常。 当然有专门的权限可以使程序代码跳过(可以理解成不进行)代码验证。 默认情况下本机程序拥有所有权限,所以修改readonly字段没有异常。当在部分信任的环境下程序集可以收到System.Security.VerificationException代表代码验证异常。 < C#, const, readonly, 区别, 只读字段, 深入解析, 破解 > 习近平任中央网络安全和信息化领导小组组长 2014 年 2 月 28 日 / 小侃 发表于 业内新闻 / 尚无评论 新华网北京2月27日电?今天,中央网络安全和信息化领导小组宣告成立,在北京召开了第一次会议。中共中央总书记、国家主席、中央军委主席习近平亲自担任组长,李克强、刘云山任副组长,再次体现了中国最高层全面深化改革、加强顶层设计的意志,显示出在保障网络安全、维护国家利益、推动信息化发展的决心。 尽管此前国内外有过诸多猜测,但这一消息还是引发了中外媒体和网民的热切关注。舆论普遍认为,这是中共落实十八届三中全会精神的又一重大举措,是中国网络安全和信息化国家战略迈出的重要一步,标志着这个拥有6亿网民的网络大国加速向网络强国挺进。 今年是中国接入国际互联网20周年。20年来,中国互联网抓住机遇,快速推进,成果斐然。据中国互联网网络信息中心发布的报告,截止2013年底,中国网民规模突破6亿,其中通过手机上网的网民占80%;手机用户超过12亿,国内域名总数1844万个,网站近400万家,全球十大互联网企业中我国有3家。2013年网络购物用户达到3亿,全国信息消费整体规模达到2.2万亿元人民币,同比增长超过28%,电子商务交易规模突破10万亿元人民币。中国已是名副其实的“网络大国”。 但是另外一些数据却显示,大不一定强,中国离网络强国目标仍有差距。我们在自主创新方面还相对落后,区域和城乡差异比较明显,特别是人均带宽与国际先进水平差距较大,国内互联网发展瓶颈仍然较为突出。以信息化驱动工业化、城镇化、农业现代化、国家治理体系和治理能力现代化的任务十分繁重。我国不同地区间“数字鸿沟”及其带来的社会和经济发展问题都需要尽快解决。同时,中国面临的网络安全方面的任务和挑战日益复杂和多元。中国目前是网络攻击的主要受害国。仅2013年11月,境外木马或僵尸程序控制境内服务器就接近90万个主机IP。侵犯个人隐私、损害公民合法权益等违法行为时有发生。 我国网络管理体制由于历史原因,造成“九龙治水”的管理格局。习近平总书记在对中共十八届三中全会《决定》的说明中明确表示,“面对互联网技术和应用飞速发展,现行管理体制存在明显弊端,多头管理、职能交叉、权责不一、效率不高。同时,随着互联网媒体属性越来越强,网上媒体管理和产业管理远远跟不上形势发展变化。” 去年以来,中国政府采取了一系列重大举措加大网络安全和信息化发展的力度。《国务院关于促进信息消费扩大内需的若干意见》强调,加强信息基础设施建设,加快信息产业优化升级,大力丰富信息消费内容,提高信息网络安全保障能力。十八届三中全会《决定》明确提出,要坚持积极利用、科学发展、依法管理、确保安全的方针,加大依法管理网络力度,完善互联网管理领导体制。 放眼世界,各国都在大力加强网络安全建设和顶层设计。截止目前,已有40多个国家颁布了网络空间国家安全战略,仅美国就颁布了40多份与网络安全有关的文件。美国还在白宫设立“网络办公室”,并任命首席网络官,直接对总统负责。2014年2月,总统奥巴马又宣布启动美国《网络安全框架》。德国总理默克尔2月19日与法国总统奥朗德探讨建立欧洲独立互联网,拟从战略层面绕开美国以强化数据安全。欧盟三大领导机构明确,计划在2014年底通过欧洲数据保护改革方案。作为中国亚洲邻国,日本和印度也一直在积极行动。日本2013年6月出台《网络安全战略》,明确提出“网络安全立国”。印度2013年5月出台《国家网络安全策略》,目标是“安全可信的计算机环境”。因此,接轨国际,建设坚固可靠的国家网络安全体系,是中国必须作出的战略选择。 中央网络安全和信息化建设领导小组的成立正是在此大背景下,落实十八届三中全会精神,以规格高、力度大、立意远来统筹指导中国迈向网络强国的发展战略,在中央层面设立一个更强有力、更有权威性的机构。 新设立的中央网络安全和信息化领导小组将着眼国家安全和长远发展,统筹协调涉及经济、政治、文化、社会及军事等各个领域的网络安全和信息化重大问题,研究制定网络安全和信息化发展战略、宏观规划和重大政策,推动国家网络安全和信息化法治建设,不断增强安全保障能力。 2014年是中国推进全面深化改革的第一年,也是中央网络安全和信息化领导小组的开局之年。毫无疑问,网络安全与信息化发展的“破题之笔”将受到广泛关注。据了解,一些工作将摆在重要位置,如:制定一个全面的信息技术、网络技术研究发展战略,下大气力解决科研成果转化问题。出台支持企业发展的政策,让他们成为技术创新主体,成为信息产业发展主体,成为维护网络安全主体。通过建立新的体制,实现军民优势互补、融合发展。制定立法规划,完善互联网信息内容管理、关键信息基础设施保护等法律法规,对重要技术产品和服务提出安全管理要求。习近平总书记在讲话中还特别提到,汇聚人才资源,建设一支政治强、业务精、作风好的强大团队,培养造就世界水平的科学家、网络科技领军人才、卓越工程师、高水平创新团队。 习近平总书记指出,“没有网络安全,就没有国家安全;没有信息化,就没有现代化。”会上透露出来的信息显示,领导小组将围绕“建设网络强国”,重点发力以下任务:要有自己的技术,有过硬的技术;要有丰富全面的信息服务,繁荣发展的网络文化;要有良好的信息基础设施,形成实力雄厚的信息经济;要有高素质的网络安全和信息化人才队伍;要积极开展双边、多边的互联网国际交流合作。会议还强调,建设网络强国的战略部署要与“两个一百年”奋斗目标同步推进,向着网络基础设施基本普及、自主创新能力增强、信息经济全面发展、网络安全保障有力的目标不断前进。 分析认为,清朗的网络空间建设将会成为一项长期任务。在2013年打击网络谣言专项行动的基础上,有关部门将进一步集中精力、集中力量对网络谣言、淫秽色情等有害信息进行“大清理”、“大扫除”;将创新改进网上宣传,运用网络传播规律,弘扬主旋律,激发正能量,大力培育和践行社会主义核心价值观。 < 中央网络安全和信息化领导小组, 习近平, 组长 > C#高级编程:Invalidate()方法学习 2014 年 2 月 21 日 / 小侃 发表于 WIN程序开发 / 尚无评论 Invalidate()是System.Windows.Forms.Form的一个成员,它把客户窗口区域标记为无效,因此在需要重新绘制时,它可以确保引发Paint事件。Invalidate()有两个重载方法:可以给它传送一个矩形,指定(使用页面坐标)需要重新绘制哪个窗口区域,如果不提供任何参数,它就把整个客户区域标记为无效。 为什么要这么做如果知道需要绘制某些内容,为什么不调用OnPaint()或直接完成绘制任务的其他方法一般情况下,最好不要直接调用绘图例程,如果代码要完成某些绘图任务,此时一般应调用Invalidate()。其原因如下所示: ● 绘图总是GDI+应用程序可以执行的一种处理器密集型的任务。在其他工作的中间进行绘图会妨碍其他工作的进行。在前面的示例中,如果在LoadFile()方法中直接调用一个方法来完成绘图,LoadFile()方法就将在绘图工作完成后才能返回。在这段时间里,应用程序不会响应其他事件。另一方面,通过调用Invalidate(),在从LoadFile返回之前,就可以让Windows引发一个Paint事件。接着Windows就可以检查等待处理的事件了。其内部的工作方式是事件被当作消息队列中一个消息。Windows会定期检查该队列,如果其中有事件,Windows就选择它,并调用相应的事件处理程序。现在Paint事件是队列中的惟一事件,所以OnPaint()会被立即调用。但是,在一个比较复杂的应用程序中,可能会有其他事件,其中一些的优先权比OnPaint()高。特别是如果用户已决定退出应用程序,该事件就会用消息WM_QUIT来标记。 ● 与第一个原因相关,如果有一个比较复杂的多线程应用程序,就会希望用一个线程处理所有的绘图操作。使用Invalidate()可以把所有的绘图操作传递到信息队列中,这有助于确保无论其他线程请求什么绘图操作,都由同一个线程完成所有的绘图操作(无论什么线程负责信息队列,都是由线程Application.Run()处理绘图操作)。 ● 还有一个与性能有关的原因。假定在某一时刻有几个不同的屏幕绘制请求,也许代码仅能修改文档,以确保显示更新的文档,而同时用户刚刚移开另一个覆盖部分客户区域的窗口。调用Invalidate(),可以让Windows注意到发生的事件。Windows就会在需要时合并Paint事件,合并无效的区域,这样绘图操作就只执行一次。 ● 最后,执行绘图的代码可能是应用程序中最复杂的代码部分,特别是当有一个比较专业化的用户界面时,就更是如此。需要长时间维护该代码的人员希望我们把所有的绘图代码都放在一个地方,且尽可能简单—— 如果程序的其他部分没有过多的路径进入该代码部分,维护就更容易。 其底线是最好把所有的绘图代码都放在OnPaint()例程中,或者在该方法中调用的其他方法中。但是要维持一个平衡。如果要在屏幕上替换一个字符,最好不要影响到已经绘制好的其他内容,此时可能不需要使用Invalidate(),而只需编写一个独立的绘图例程。 注意: 在非常复杂的应用程序中,甚至可以编写一个完整的类,专门负责在屏幕上绘图。几年前MFC仍是GDI密集型应用程序的标准技术,MFC就遵循这个模式,使用一个C++类CView完成绘图操作。但即使是这样,这个类也有一个成员函数OnDraw(),用作大多数绘图请求的入口点。 转自:http://www.tzwhx.com/newOperate/html/1/12/124/10475.html C#中Invalidate() 方法 重载列表 使控件的特定区域无效并向控件发送绘制消息。 受 .NET Framework 精简版的支持。 [C#] public void Invalidate();[C++] public: void Invalidate();使控件的特定区域无效并向控件发送绘制消息。还可以使分配给该控件的子控件无效。 [C#] public void Invalidate(bool);使控件的指定区域无效(将其添加到控件的更新区域,下次绘制操作时将重新绘制更新区域),并向控件发送绘制消息。 受 .NET Framework 精简版的支持。 [C#] public void Invalidate(Rectangle);使控件的指定区域无效(将其添加到控件的更新区域,下次绘制操作时将重新绘制更新区域),并向控件发送绘制消息。 [C#] public void Invalidate(Region);使控件的指定区域无效(将其添加到控件的更新区域,下次绘制操作时将重新绘制更新区域),并向控件发送绘制消息。还可以使分配给该控件的子控件无效。 [C#] public void Invalidate(Rectangle, bool);使控件的指定区域无效(将其添加到控件的更新区域,下次绘制操作时将重新绘制更新区域),并向控件发送绘制消息。还可以使分配给该控件的子控件无效。 [C#] public void Invalidate(Region, bool);示例 [Visual Basic, C#, C++] 下面的示例使用户能够将图像或图像文件拖到窗体上,并使它在放置点显示。每次绘制窗体时,都重写 OnPaint 方法以重新绘制图像;否则图像将保持到下一次重新绘制。DragEnter 事件处理方法决定拖到窗体中的数据的类型,并提供适当的反馈。如果 Image 可以从该数据中创建,则 DragDrop 事件处理方法就会在该窗体上显示此图像。因为 DragEventArgs.X 和 DragEventArgs.Y 值为屏幕坐标,所以示例使用 PointToClient 方法将它们转换成工作区坐标。 < C#, Invalidate(), 方法学习, 高级编程 > C#结构体类型基础详解 2014 年 2 月 21 日 / 小侃 发表于 WIN程序开发 / 尚无评论 结构是使用?struct?关键字定义的,与类相似,都表示可以包含数据成员和函数成员的数据结构。 一般情况下,我们很少使用结构,而且很多人也并不建议使用结构,但作为.NET Framework 一般型別系统中的一个基本架构,还是有必要了解一下的。 结构的特征: 结构是一种值类型,并且不需要堆分配。 结构的实例化可以不使用?new?运算符。 在结构声明中,除非字段被声明为?const 或 static,否则无法初始化。 结构类型永远不是抽象的,并且始终是隐式密封的,因此在结构声明中不允许使用abstract和sealed修饰符。 结构不能声明默认构造函数(没有参数的构造函数)或析构函数,但可以声明带参数的构造函数。 结构可以实现接口,但不能从另一个结构或类继承,而且不能作为一个类的基类,所有结构都直接继承自?System.ValueType,后者继承自?System.Object。 结构在赋值时进行复制。?将结构赋值给新变量时,将复制所有数据,并且对新副本所做的任何修改不会更改原始副本的数据。?在使用值类型的集合(如 Dictionary<string, myStruct>)时,请务必记住这一点。 结构类型的变量直接包含了该结构的数据,而类类型的变量所包含的只是对相应数据的一个引用(被引用的数据称为“对象”)。但是结构仍可以通过ref和out参数引用方式传递给函数成员。 结构可用作可以为 null 的类型,因而可向其赋 null 值。 struct A { public int x; //不能直接对其进行赋值 public int y; public static string str = null; //静态变量可以初始化 public A(int x,int y) //带参数的构造函数 { this.x = x; this.y = y; Console.WriteLine("x={0},y={1},str={2}", x, y,str); } } class Program { static void Main(string[] args) { A a =new A(1,2); A a1 = a; a.x =10; Console.WriteLine("a1.x={0}",a1.x); Console.Read(); } } 结果为:x=1,y=2,str= a1.x=1 此时a1.x值为1是因为,将a赋值给a1是对值进行复制,因此,a1不会受到a.x赋值得改变而改变。 但如果A是类,这时a和a1里的x引用的是同一个地址,则a1.x的值会输出10。 结构的装箱与拆箱 我们知道,一个类类型的值可以转换为object类型或由该类实现的接口类型,这只需在编译时把对应的引用当作另一个类型处理即可。 与此类似,一个object?类型的值或者接口类型的值也可以被转换回类类型而不必更改相应的引用。当然,在这种情况下,需要进行运行时类型检查。 由于结构不是引用类型,上述操作对结构类型是以不同的方式实现的。 当结构类型的值被转换为object?类型或由该结构实现的接口类型时,就会执行一次装箱操作。 反之,当?object?类型的值或接口类型的值被转换回结构类型时,会执行一次拆箱操作。 与对类类型进行的相同操作相比,主要区别在于: 装箱操作会把相关的结构值复制为已被装箱的实例,而拆箱则会从已被装箱的实例中复制出一个结构值。 因此,在装箱或拆箱操作后,对“箱”外的结构进行的更改不会影响已被装箱的结构。 struct Program { static void Main(string[] args) { int i =1; object o = i; //隐式装箱 i =123; Console.WriteLine("i={0},o={1}",i,o); Console.Read(); } } //结果为:i=123,o=1 结构与构造函数 我们知道结构不能使用默认的构造函数,只能使用带参数的构造函数,当定义带参数的构造函数时,一定要完成结构所有字段的初始化,如果没有完成所有字段的初始化,编译时会发生错误-。 结构可以使用静态构造函数吗? 可以,结构的静态构造函数与类的静态构造函数所遵循的规则大体相同。 结构的静态构造函数何时将触发呢? 结构的实例成员被引用,结构的静态成员被引用,结构显示声明的构造函数被调用。 但是创建结构类型的默认值不会触发静态构造函数。 为什么结构不能自定义无参数的构造函数? 结构类型的构造函数与类的构造函数类似,用来初始化结构的成员变量,但是struct不能包含显式默认构造函数, 因为编译器将自动提供一个构造函数,此构造函数将结构中的每个字段初始化为默认值表中显示的默认值。 然而,只有当结构用new实例化时,才会调用此默认构造函数。对值类型调用默认构造函数不是必需的。 struct A { static A() { Console.WriteLine("I am A."); } public void Fun() { } } class Program { static void Main(string[] args) { A a=new A(); a.Fun(); //结构的实例成员被引用 Console.Read(); } } 结果为:I am A. 结构与继承: 一个结构声明可以指定实现的接口列表,但是不能指定基类。 由于结构不支持类与结构的继承,所以结构成员的声明可访问性不能是protected或protected?internal。 结构中的函数成员不能是?abstract或?virtual,因而?override修饰符只适用于重写从System.ValueType继承的方法。 为在设计编程语言时将结构设计成无继承性?- 其实类的继承是有相当的成本的 ——由于继承性,每个类需要用额外的数据空间来存储“继承图”来表示类的传承历史, 通俗地说来就是我们人类的家族家谱,里面存储着我们的祖宗十八代,只有这样我们才知道我们从哪里来的,而家谱肯定是需要额外的空间来存放的。 大家不要觉得这个存放“继承图”的空间很小,如果我们的程序需要用10000个点(Point)来存放游戏中的人物形体数据的话, 在一个场景中又有N个人,这个内存开销可不是小数目了。所以我们可以通过将点(Point)申明成 Struct而不是class来节约内存空间。 interface ITest { void Fun(int x,int y); } struct A:ITest { public void Fun(int x,int y) //隐式实现接口里的方法 { Console.WriteLine("x={0},y={1}", x, y); } } class Program { static void Main(string[] args) { A a; //结构的实例化可以不使用new a.Fun(1, 2); Console.Read(); } } // 结果为:x=1,y=2 什么情况下结构的实例化可以不使用new? 当结构中没有参数时,结构的实例化可以不使用new; 当结构中有参数时,必须对结构中所有参数进行初始化后,才能不使用new对结构进行实例化。 什么时候使用结构? 结构体适合一些小型数据结构,这些数据结构包含的数据以创建结构后不修改的数据为主; 例如:struct类型适于表示Point、Rectangle和Color等轻量对象。 尽管可以将一个点表示为类,但在某些情况下,使用结构更有效。 如果声明一个10000个Point对象组成的数组,为了引用每个对象,则需分配更多内存;这种情况下,使用结构可以节约资源。- 定义的时候不会用到面向对象的一些特性; 结构体在不发生装箱拆箱的情况下性能比类类型是高很多的. < C#, 基础, 类型, 结构体, 详解 > MonoBehaviour类Invoke, Coroutine 2014 年 2 月 18 日 / 小侃 发表于 游戏开发 / 尚无评论 MonoBehaviour概述 MonoBehaviour 表示一个单一的行为。Unity中用户对游戏对象的操作被分割成若干个单一行为。每个单一行为都作为一个MonoBehaviour类来封装。再生成每个MonoBehaviour类的实例,并作为组件嵌入游戏对象。然后按照一定的顺序(从下到上)调用每个对象的重载方法来实现游戏对象的全部行为。 创建 在菜单Assets->create中选择javascript活C# script创建一个脚本类。Unity规定:这些类都必须继承自MonoBehaviour。javascript 的脚本类自动继承MonoBehaviour,c#脚本类必须显式继承这个类。 特别之处 继承自MonoBehaviour的类,不需要自己创建它的实例,也不能自己创建(如 new 类名)。因为所有从MonoBehaviour继承过来的类,unity都会自动创建实例,并且调用被重载的方法,如我们经常用到的Awake,Start, Update等。而普通类,就可以用new来创建实例了。 异步函数 在一个方法执行时调用另一个方法。而被调用的方法或者其中的某些语句不是立刻执行,而是过一段时间后才执行。 MonoBehaviour提供了两种异步方法 调用(Invoke) 协程(Coroutine) 调用(Invoke) function Invoke (methodName: string, time : float) : void functionInvokeRepeating (methodName :?String,time : float, repeatRate : float) : void function CancelInvoke () : void function IsInvoking (methodName: string) : bool 协程(Coroutine) function StartCoroutine (routine: IEnumerator) : Coroutine function StartCoroutine (methodName: string, value : object = null) : function StopCoroutine (methodName: string) : void function StopAllCoroutines () : void 协程介绍 协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈,局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。线程与协同程序的主要区别在于,一个具有多线程的程序可以同时运行几个线程,而协同程序却需要彼此协作地运行。就是说,一个具有多个协同程序的程序在任何时刻只能运行一 个协同程序,并且正在运行的协同程序只会在其显示地挂起时,它的执行才会暂停。 Unity中协程 一个协同程序在执行过程中,可以在任意位置使用yield语句。yield的返回值控制何时恢复协同程序向下执行。协同程序在对象自有帧执行过程中堪称优秀。协同程序在性能上没有更多的开销。StartCoroutine函数是立刻返回的,但是yield可以延迟结果。直到协同程序执行完毕。 function StartCoroutine (routine: IEnumerator) : Coroutine 参数表:IEnumerator IEnumerator是枚举数接口。函数需要一个实现了这个接口的YieldInstruction对象。可以创建一个WaitForSeconds对象,在它的构造函数中传入挂起时间。 返回值:Coroutine 只用来表示一个协同程序实例的引用。没有任何暴露的变量和函数。一个coroutine是一个函数,它能在中断完成前挂起执行。 function StartCoroutine (methodName: string, value : object = null) :?Coroutine 直接传入一函数名,开销大些。 比较 Invoke方法:执行没有被挂起,相当于设置完被调用函数的执行时间后即时向下执行。应用到没隔一段时间执行某个函数很方便。 Coroutine方法:新开一条执行序列(跟新建线程差不多)并挂起,等待中断指令结束。开销不大。当需要挂起当前执行时使用。比如Player死了一条命后消失,再过1.5秒后重新出现,就可以用将协同程序挂起。 gameObject.renderer.enabled= false; yieldWaitForSeconds(1.5f); gameObject.renderer.enabled= true; < Coroutine, Invoke, MonoBehaviour, Unity > Unity引擎中的HotKeys 2014 年 2 月 18 日 / 小侃 发表于 游戏开发 / 尚无评论 好久都没有更新博客了,最近在忙于整理一些东西,所以就疏远了更新的进度了。下面弄了2张截图,是有关Unity3d的hotkeys组合。 第一幅截图是window下的unity3d中引擎的快捷操作键。 第二幅截图是Mac下unity3d引擎中的操作快捷键。 至于,我们在玩游戏时的操作快捷方式,是可以再游戏开发中进行设置的。这个就不细说了,大家也都清楚的!有机会,会在以后的博客中进行详述的。 < HotKeys, Unity, 引擎 > Unity3D Student 教程观看笔记整理 2014 年 2 月 18 日 / 小侃 发表于 游戏开发 / 尚无评论 一.Unity3D Student教程基础 1.工程 Unity的工程文件实际上是有一个文件夹下的所有文件组成的.在Unity下你必须在一整个文件夹下进行工作.这个文件夹,一个是assets,一个Library.在运行的时候会有一个临时文件夹[temporary]的文件夹. 2.场景 你可以放你所看到的一切.每个场景新建的话都会有一个住摄像机.场景视图中你可以通过手型工具进行导航监视.手型可以让你进行拖拽平移视图.按下alt来旋转视图.按下ctrl来缩放视图(mac是command键). 注意:如果你奥查找的物件没有在视图中,你可以在层次面板中选中这个物件,把鼠标放到场景视图中,按F键.在场景视图中会让选中的物件居中.搜索物件. 3.层次面板 层次面板中列举了游戏场景中所有的物件,而且还负责着组织物件之间的&#8221;父子关系&#8221;!你可以通过层次面板搜索到场景视图中看到的物件. 4.游戏视图 Unity一个很不错的特性就是让你很直观的编译和测试游戏. 如果想要摄像机从某个角度进行拍摄,并让游戏视图和场景视图看上去一样,首先我们选择&#8221;主摄像机&#8221;,在选择游戏物件菜单中的对齐到视图(Align with View). 注意:在测试状态中你可以对游戏场景的各个熟悉进行修改.他只会在这种状态下体现出修改后的效果,但是任何做出的编辑和改变,都不会被保存.在||中你额可以在暂停状态检查游戏的性能数据等.Gizmos是一般来说是一些较小的2D的信息展示用的标志(如光源图标).我们也可以通过自定义脚本来控制Gizmo的展示形式. 5.工程面板 我们编译的资源都在这里了. 6.游戏物件 目前我们知道的即时物件存在与当前场景中的一些东西.存放在层次面板中. 7.组件 你可以通过组件菜单来为不同的物体添加各种各样的组件. 8.资源导入 a.直接双击导入. b.通过资源菜单导入 为不同的平台制作不同的贴图. 导入和导出资源. 在里面可以选择自己想要导入的资源! 9.光源 有三种光源. 直射光,点光源,聚光灯 10.摄像机 当你通过场景视图看到的场景并不一定和游戏视图中的一样.一般来说游戏视图展示的才是摄像机的视野.一般游戏中,摄像机都会绑定在某个物件上.通过控制物件的移动来控制摄像机的移动.我们可以让摄像机成为某个物件的子物件.也可以创建一个脚本来控制摄像机和某个物件之间的关系.摄像机往往也是玩家在游戏场景中听到声音的位置.所以,我们要记住摄像机所在的位置.会影响到场景中不同音频源的声音大小.这取决于听者和声源之间的距离. 在主摄像机旁边的声音将会听上去小声一些.在游戏过程中,我们可以通过脚本控制哪个摄像机需要被激活. 二.Unity3D Student 教程 初学者 1.如何使用重力? 给组件添加一个刚体组件.我们可以给碰撞器添加不用的物理材质,让他具有不同的物理效果. 2.碰撞检测基础知识 我们建一个脚本,来编写我们的逻辑.在OnCollistionEnter函数中,添加逻辑代码. 在这个函数中我们可以传递参数进行碰撞物体的检测. 检测用户输入的代码应该放入到Update函数中,因为用户随时可能发生,你应该在游戏每帧执行时检测他. 3.预制件 预制件就是一个被存为模版的物件.你可以通过这个预制件克隆出来很多相同属性设置的物件实体. 4.销毁指令 如果想从场景中移出任何物件(即销毁对象),应该在脚本中使用Destroy方法!方法中传的是我们要销毁的对象.这个脚本执行过程就会在层次面板的内容中找到这个名字的物件然后销毁他. 5.实例化 如果你想在场景中动态的创建物件,这时就需要使用脚本命令Instantiate来动态实例化物件. 6.做一个简单的计时器 7.移动基础 transfrom-空间信息组件 包含&#8221;位置&#8221;,&#8221;旋转&#8221;,&#8221;缩放&#8221;. 这里需要记住在监视面板上调整变量的值不会改变脚本中的值. 8.施加力 一个有刚体的物件,需要通过施加力使其运动.因为物件在游戏过程中一直受到物理引擎的影响,使用普通的平移会和物理引擎的控制产生冲突. 我们可以对其施加一个力或者Constant Force 恒定力,使其运动.可以对物件使用多次的力. 9.材质 如果你想修改物件的外观时,便需要掌握材质. 10.声音 播放声音需要注意两点:监听器和音源组件.一般而言监视器会是摄像机的一个组件. 11.关节 固定关节,枢纽关节.在这个链接的过程中,如果没有给物体添加刚体,就不能进行关节的相关操作. 12.输入 unity中的输入有另外一种类型Axis-轴.鼠标是左键0,右键1,键盘是其他,在-1和1之间进行变换. 13.触发器 如果不想让碰撞检测影响物件移动,但是有想检测到碰撞.那么你应该使用Trigger-触发器.触发器经常被用来检测一个物件是否可经过空间中的某个区域.Is Trgger用处是可以用这中方式碰撞不被玩家&#8221;看见&#8221;,用来检测某个物件是否在某个特定的区域. 14.GUI Text图形界面文本 GUI是一种用于展示游戏状态的常用方式.加空字符进行类型数值类型的转换. < Student, unity3d, 教程, 整理, 观看笔记 > Unity3d之MonoBehaviour的可重写函数整理 2014 年 2 月 18 日 / 小侃 发表于 游戏开发 / 尚无评论 Update 当MonoBehaviour启用时,其Update在每一帧被调用。 LateUpdate 当Behaviour启用时,其LateUpdate在每一帧被调用。 FixedUpdate 当MonoBehaviour启用时,其 FixedUpdate 在每一帧被调用。 Awake 当一个脚本实例被载入时Awake被调用。 Start Start仅在Update函数第一次被调用前调用。 Reset 重置为默认值。 OnMouseEnter 当鼠标进入到GUIElement(GUI元素)或Collider(碰撞体)中时调用OnMouseEnter。 OnMouseOver 当鼠标悬浮在GUIElement(GUI元素)或Collider(碰撞体)上时调用 OnMouseOver . OnMouseExit 当鼠标移出GUIElement(GUI元素)或Collider(碰撞体)上时调用OnMouseExit。 OnMouseDown 当鼠标在GUIElement(GUI元素)或Collider(碰撞体)上点击时调用OnMouseDown。 OnMouseUp 当用户释放鼠标按钮时调用OnMouseUp。 OnMouseUpAsButton OnMouseUpAsButton只有当鼠标在同一个GUIElement或Collider按下,在释放时调用。 OnMouseDrag 当用户鼠标拖拽GUIElement(GUI元素)或Collider(碰撞体)时调用 OnMouseDrag 。 OnTriggerEnter 当Collider(碰撞体)进入trigger(触发器)时调用OnTriggerEnter。 OnTriggerExit 当Collider(碰撞体)停止触发trigger(触发器)时调用OnTriggerExit。 OnTriggerStay 当碰撞体接触触发器时,OnTriggerStay将在每一帧被调用。 OnCollisionEnter 当此collider/rigidbody触发另一个rigidbody/collider时,OnCollisionEnter将被调用。 OnCollisionExit 当此collider/rigidbody停止触发另一个rigidbody/collider时,OnCollisionExit将被调用。 OnCollisionStay 当此collider/rigidbody触发另一个rigidbody/collider时,OnCollisionStay将会在每一帧被调用。 OnControllerColliderHit 在移动的时,当controller碰撞到collider时OnControllerColliderHit被调用。 OnJointBreak 当附在同一对象上的关节被断开时调用。 OnParticleCollision 当粒子碰到collider时被调用。 OnBecameVisible 当renderer(渲染器)在任何相机上可见时调用OnBecameVisible。 OnBecameInvisible 当renderer(渲染器)在任何相机上都不可见时调用OnBecameInvisible。 OnLevelWasLoaded 当一个新关卡被载入时此函数被调用。 OnEnable 当对象变为可用或激活状态时此函数被调用。 OnDisable 当对象变为不可用或非激活状态时此函数被调用。 OnDestroy 当MonoBehaviour将被销毁时,这个函数被调用。 OnPreCull 在相机消隐场景之前被调用。 OnPreRender 在相机渲染场景之前被调用。 OnPostRender 在相机完成场景渲染之后被调用。 OnRenderObject 在相机场景渲染完成后被调用。 OnWillRenderObject 如果对象可见每个相机都会调用它。 OnGUI 渲染和处理GUI事件时调用。 OnRenderImage 当完成所有渲染图片后被调用,用来渲染图片后期效果。 OnDrawGizmosSelected 如果你想在物体被选中时绘制gizmos,执行这个函数。 OnDrawGizmos 如果你想绘制可被点选的gizmos,执行这个函数。 OnApplicationPause 当玩家暂停时发送到所有的游戏物体。 OnApplicationFocus 当玩家获得或失去焦点时发送给所有游戏物体。 OnApplicationQuit 在应用退出之前发送给所有的游戏物体。 OnPlayerConnected 当一个新玩家成功连接时在服务器上被调用。 OnServerInitialized 当Network.InitializeServer被调用并完成时,在服务器上调用这个函数。 OnConnectedToServer 当你成功连接到服务器时,在客户端调用。 OnPlayerDisconnected 当一个玩家从服务器上断开时在服务器端调用。 OnDisconnectedFromServer 当失去连接或从服务器端断开时在客户端调用。 OnFailedToConnect 当一个连接因为某些原因失败时在客户端调用。 OnFailedToConnectToMasterServer 当报告事件来自主服务器时在客户端或服务器端调用。 OnMasterServerEvent 当报告事件来自主服务器时在客户端或服务器端调用。 OnNetworkInstantiate 当一个物体使用Network.Instantiate进行网络初始化时调用。 OnSerializeNetworkView 在一个网络视图脚本中,用于自定义变量同步。 < MonoBehaviour, unity3d, 可重写函数, 整理 > .net中字符串的常用方法 2014 年 2 月 17 日 / 小侃 发表于 WIN程序开发 / 尚无评论 字符串重要的一些属性: 1、Length:获得字符串中字符的个数。 举例如下: 01.<FONTface=微软雅黑>string str = &#8220;hello&#8221;; 02.Console.WriteLine(str.Length); 03.//输出结果为:5 04.//即该字符串长度为5</FONT> 复制代码二、常用方法 1、IsNullOrEmpty():判断字符串是否为空或者为null 举例如下: 01.<FONTface=微软雅黑>string str = &#8220;&#8221;; 02.if(string.IsNullOrEmpty(str)) 03.{ 04.Console.WriteLine(&#8220;该字符串为空,或为null&#8221;); 05.} 06.else 07.{ 08.Console.WriteLine(str); 09.} 10.//输出结果为:该字符串为空,或为null 11.//这里,stringstr=null,输出结果也为:该字符串为空,或为null 12.//注意:该方法为静态方法,调用时必须?类名.方法名?调用。</FONT> 复制代码 2、ToCharrArry():将string转换成char数组 举例如下: 01.? ?string str = &#8220;hello&#8221;; 02.? ?char[] c = str.ToCharArray(); 03.? ?c[1] = &#8216;a&#8217;; 04.? ?Console.WriteLine(new string(c)); 05.//输出结果为:hallo 06.//因为字符串的不可改变性,要修改字符串中的某个字符,必须ToCharArray()拆分成一个char数组。 复制代码 3、ToLower()?:将一个字符串转换成小写。 举例如下: 01.stringstr = &#8220;HELLO&#8221;; 02.strings = str.ToLower(); 03.Console.WriteLine(s); 04.//输出结果:hello 05.//注意:必须声明一个变量来接受返回值(s),因为字符串的不可改变性。 复制代码 4、Equals():将一个字符换转换成大写 举例如下: 01.stringstr = &#8220;hello&#8221;; 02.strings = str.Equals(); 03.Console.WriteLine(s); 04.//输出结果为:HELLO 复制代码 5、Equals():比较两个字符串是否相同 举例如下: 01.strings1 =&#8221;hello&#8221;; 02.strings2 = &#8220;HELLO&#8221;; 03.if(s1.Equals(s2)) 04.{ 05.Console.WriteLine(&#8220;两个字符串一样&#8220;); 06.} 07.else 08.{ 09.Console.WriteLine(&#8220;两个字符串不一样&#8220;); 10.} 11.//输出结果:两个字符串不一样 12.//因为大小写不同,所以两个字符串是不一样 13. 14. 15.strings1 =&#8221;hello&#8221;; 16.strings2 = &#8220;HELLO&#8221;; 17.if(s1.Equals(s2,StringComparison.OrdinalIgnoreCase)) 18.{ 19.Console.WriteLine(&#8220;两个字符串一样&#8220;); 20.} 21.else 22.{ 23.Console.WriteLine(&#8220;两个字符串不一样&#8220;); 24.} 25.//输出结果:两个字符串一样。 26.//这里我们使用了Equals的第二个重载,该重载第二个参数StringComparison.OrdinalIgnoreCase是一个枚举//值,用来忽略大小写。 复制代码 6、IndexOf():检索字符串中指定的字符的索引。 举例如下: 01.stringstr = &#8220;大家好,我叫小明,我今年12岁了!大家要记住我叫小明哦!&#8220;; 02.int n= str.IndexOf(&#8220;小明&#8220;); 03.Console.WriteLine(n); 04.//输出结果为:6 05.//以为“小明”,即&#8220;小&#8220;的索引6、“明”的索引为7,即“小明”的索引为6、7 06. 07. 08.stringstr = &#8220;大家好,我叫小明,小明今年12岁了!&#8220;; 09.int n= str.IndexOf(&#8220;小明&#8220;,7); 10.Console.WriteLine(n); 11.//输出结果为:9 12.//这里我们发现9真好是第二个“小明”的索引。因为这里我们调用了IndexOf(string value,int startIndex)这个重载,即?startIndex=检索开始的地方。 13. 14. 15.stringstr = &#8220;大家好,我叫小明,小明今年12岁了!&#8220;; 16.int n= str.IndexOf(&#8220;小胖&#8220;); 17.Console.WriteLine(n); 18.//输出结果为:-1 19.//即如果检索不到相应的数据,则返回值为:-1 20. 21.//注意:1、IndexOf返回值为int类型 22.? ?? ?? ?? ???2、IndexOf共有8个重载,不仅仅只能传入一个字符串,还能是一个char,还能指定要检索字符的类型等。。。希望自己在使用的过程中都了解一下这些重载。 23. 复制代码 7、LastIndexOf():检索字符串中指定字符最后一个的索引。 举例如下: 01.stringstr = &#8220;大家好,我叫小明,小明今年12岁了!&#8220;; 02.int n= str.LastIndexOf(&#8220;小明&#8220;); 03.Console.WriteLine(n); 04.//输出结果为:9 05.//这里直接忽略第一个&#8220;小明&#8220;,返回最后一个&#8220;小明&#8220;的索引。 06. 复制代码 8、Substring():截取字符串 举例如下: 01.stringstr = &#8220;大家好,我叫小明,小明今年12岁了!&#8220;; 02.stringstr1 = str.Substring(4); 03.Console.WriteLine(str1); 04.//输出结果为:我叫小明,小明今年12岁了! 05.//即从索引4开始截取(含4),截取到最后 06. 07.stringage = str.Substring(13,2); 08.Console.WriteLine(age); 09.//输出结果为:12 10.//即从索引13开始截取(含13),截取2个字符 复制代码 9、Split():将指定字符串按某指定的分隔符进行拆分,拆分将会形成一个字符串的数组并返回 01.//根据一个字符来分割 02.stringname = &#8220;小|明-小|花-小|胖-小|美&#8220;; 03.string[]strName = name.Split(&#8216;-&#8217;); 04.for(inti = 0;i < strName.Lengeh;i++) 05.{ 06.? ? Console.Write(strName); 07.} 08.//输出结果为:小|明小|花小|胖小|美 09. 10.//根据一个字符串数组来分割 11.string[]strName = name.Split(new string[]{&#8220;-&#8221;,&#8221;|&#8221;},StringSplitOptions.RemoveEmptyEntries); 12.for(inti = 0;i < strName.Lengeh;i++) 13.{ 14.Console.Write(strName); 15.} 16.//输出结果为:小明小花小胖小美 17. 18.//补充:Split()有6个重载,可以传一个char来分割,也可以传一个char[],还可以是string[] 19. 20. 复制代码 10、Join():把一个字符串数组中的每个元素,用指定的字符进行连接 举例如下: 01.stringname = &#8220;小|明-小|花-小|胖-小|美&#8220;; 02.string[]strName = name.Split(new string[]{&#8220;-&#8221;,&#8221;|&#8221;},StringSplitOptions.RemoveEmptyEntries); 03.stringstr = string.Join(&#8220;★&#8220;, strName); 04.Console.WriteLine(str); 05.//输出结果:?小★明★小★花★小★胖★小★美 06.//注意:此方法为静态方法 复制代码 11、Format():通过占位符来拼接字符串 举例如下: 01.stringname = &#8220;小明&#8220;; 02.stringsay = string.Format(&#8220;我叫{0}&#8221;,name); 03.Console.WriteLine(say); 04.//输出结果为:我叫小明 05.//注意:此方法为静态方法 复制代码 12、Replce():用指定的字符替换字符串中指定的字符 01.stringsay = &#8220;我叫小明,我今年12岁了!&#8220;; 02.stringstr = say.Replcae(&#8220;小明&#8220;,&#8221;***&#8221;); 03.Console.WriteLine(str); 04.//输出结果为:我叫***,我今年12岁了! 复制代码 13、Trim():去掉字符串两端的空格 举例如下: 01.stringname = &#8220;小明&#8220;; 02.stringstr = name.Trim(); 03.Console.WriteLine(str); 04.//输出结果为:小明 < .Net, C#, 字符串, 常用方法 > &laquo; 较旧的文章 2014年三月 一 二 三 四 五 六 日 &laquo; 二 12 3456789 10111213141516 17181920212223 24252627282930 31 TAG,云图 .Net 2亿台PC 23岁黑客入侵德国 ADO→XML C# C语言原创教程第一课 ip to long IT业务管理 MD5 MonoBehaviour Office 2010 PHP PSDHTML教程 SOAP简介 TCP连接状态 Unity unity3d VBS教程(文本版) VB.NET Vista Win7 win8 Windows8系统 XML上传文件 xml中的空格 XML创建显示页面 XML初学必读 XML动态页面 XML实现页面无刷新 XML的应用 XML的开发Jabber XML系统日志设计 YxShop任意文件上传漏洞 “云安全”联盟 产生负数 企业信息防泄漏 函数 动态增加xml 区别 国外流行PHP程序的识别 奥巴马会见达赖 实现BSM 建立自主网络 异常 忠告 推进实名制 整理 新闻集团遭入侵 方法 服务器防黑技巧 术语大全 版本号 电脑上登陆QQ显示iPhone手机在线的方法 破坏互联网 索尼黑客事件 编程语言互译 网站被收录 网络安全大患 网警密码 联想超戴尔 警方未能立案 认证 详解 诺基亚 金山、百度、MSN、腾讯 金山漏洞 防范黑客 高效编程 黑客 黑客指定下载列表 黑客攻击 基地组织 黑客攻击损失300万 黑客攻击英太阳报 黑客组织 黑客"劫持"SNS List.文章归档 2014年三月 (1) 2014年二月 (10) 2014年一月 (1) 2013年十二月 (1) 2013年十一月 (4) 2013年十月 (5) 2013年九月 (9) 2013年八月 (22) 2013年七月 (2) 2013年六月 (6) 2012年十月 (1) 2012年六月 (3) 2012年五月 (2) 2012年三月 (1) 2012年一月 (2) 2011年十二月 (13) 2011年十一月 (8) 2011年十月 (29) 2011年九月 (67) 2011年八月 (63) 2011年七月 (72) 博客链接 奠爱博客 安全焦点 尕猪&#039;s Blog 星星s&#039;Bolg 熊猫博客 羽度非凡博客 蓝盟团队博客 飞飞&#039;Blog 网站链接 90电影网 VB编程网 中国蓝客联盟 依人聊娱乐网 华文网 多特价购物网 黑客技术 黑客榜中榜 &copy;2001-2014 小侃's Blog 版权所有