C#程序员整理的Unity 3D笔记(四):脚本优化

Unity3D代码开发需要注意的地方

1. 尽量避免每帧处理

比如:

function Update() { DoSomeThing(); }

可改为每5帧处理一次:

function Update() { if(Time.frameCount % 5 == 0) { DoSomeThing(); } }

2. 定时重复处理用 InvokeRepeating 函数实现

比如,启动0.5秒后每隔1秒执行一次 DoSomeThing 函数:

function Start() { InvokeRepeating("DoSomeThing", 0.5, 1.0); }

3. 优化 Update, FixedUpdate, LateUpdate 等每帧处理的函数

Update() 和 FixedUpdate()在游戏中都会在更新的时候自动循环调用。

但是Update是在每次渲染新的一帧的时候才会调用,也就是说,这个函数的更新频率和设备的性能有关以及被渲染的物体(可以认为是三角形的数量)。在性能好的机器上可能fps 30,差的可能小些。这会导致同一个游戏在不同的机器上效果不一致,有的快有的慢。因为Update的执行间隔不一样了。

而FixedUpdate,是在固定的时间间隔执行,不受游戏帧率的影响。有点想Tick。所以处理Rigidbody的时候最好用FixedUpdate。

Unity中Update和Lateupdate的区别。Lateupdate和Update每一祯都被执行,但是执行顺序不一样,先执行Updatee然后执行lateUpdate。

如果你有两个脚本JS1、JS2,两个脚本中都有Update()函数, 在JS1中有 lateUpdate ,JS2中没有。那么 lateUpdate 函数会等待JS1、JS2两个脚本的Update()函数 都执行完后才执行。也就是说, 如果现在有100个脚本,分别有100个 Update()函数,其中只有一个LateUpdate,那么在同一祯中,等待100个Update()执行完后,才执行这一个lateUpdate()。

函数里面的变量尽量在头部声明。

比如:

function Update() { var pos: Vector3 = transform.position; }

可改为

private var pos: Vector3; function Update(){ pos = transform.position; }

4. 主动回收垃圾

给某个 GameObject 绑上以下的代码:

function Update() { if(Time.frameCount % 50 == 0) { System.GC.Collect(); } }

5. 运行时尽量减少 Tris Draw Calls

预览的时候,可点开 Stats,查看图形渲染的开销情况。特别注意 Tris 和 Draw Calls 这两个参数。

一般来说,要做到:

Tris 保持在 7.5k 以下

Draw Calls 保持在 20 以下

Tris:Game 视窗右上角 Stat 里面的Tris 记录场景内的所有三角面数

Draw Calls:

一个简单的openGL的绘图次序是:设置颜色→绘图方式→顶点座标→绘制→结束。

每帧都会重复以上的步骤。这就是一次draw call

如果有两个model,那么需要

设置颜色→绘图方式→顶点座标A→绘制→结束。

设置颜色→绘图方式→顶点座标B→绘制→结束。

两次draw calls;

也就是说在openGl绘制前,如果色彩通道(color filter),绘图方式(shader),顶点座标(model)不同的情况下draw calls就会增加。

对openGl来说绘制参数(状态值)的变更要比绘制大量的顶点更耗费cpu。

所谓高速绘图就是,在尽量不改变openGl状态值的情况下,用一次draw call完成所有绘制。

比如上面的例子:

设置颜色→绘图方式→顶点座标A+顶点座标B→绘制→结束。

就要更加有效率。

6. 压缩 Mesh

导入 3D 模型之后,在不影响显示效果的前提下,最好打开 Mesh Compression。

Off, Low, Medium, High 这几个选项,可酌情选取。

7. 避免大量使用 Unity 自带的 Sphere 等内建 Mesh

Unity 内建的 Mesh,多边形的数量比较大,如果物体不要求特别圆滑,可导入其他的简单3D模型代替。

8. 优化数学计算

比如,如果可以避免使用浮点型(float),尽量使用整形(int),尽量少用复杂的数学函数比如 Sin 和 Cos 等等

9. 减少固定增量时间

将固定增量时间值设定在0.04-0.067区间(即,每秒15-25帧)。您可以通过Edit->Project Settings->Time来改变这个值。这样做降低了FixedUpdate函数被调用的频率以及物理引擎执行碰撞检测与刚体更新的频率。如果您使用了较低的固定增量时间,并且在主角身上使用了刚体部件,那么您可以启用插值办法来平滑刚体组件。

10. 减少GetComponent的调用

使用 GetComponent或内置组件访问器会产生明显的开销。您可以通过一次获取组件的引用来避免开销,并将该引用分配给一个变量(有时称为"缓存"的引用)。例如,如果您使用如下的代码:

function Update () {

transform.Translate(0, 1, 0);

}

通过下面的更改您将获得更好的性能:

var myTransform : Transform;

function Awake () {

myTransform = transform;

}

function Update () {

myTransform.Translate(0, 1, 0);

}

11. 避免分配内存

您应该避免分配新对象,除非你真的需要,因为他们不再在使用时,会增加垃圾回收系统的开销。您可以经常重复使用数组和其他对象,而不是分配新的数组或对象。这样做好处则是尽量减少垃圾的回收工作。同时,在某些可能的情况下,您也可以使用结构(struct)来代替类(class)。这是因为,结构变量主要存放在栈区而非堆区。因为栈的分配较快,并且不调用垃圾回收操作,所以当结构变量比较小时可以提升程序的运行性能。但是当结构体较大时,虽然它仍可避免分配/回收的开销,而它由于"传值"操作也会导致单独的开销,实际上它可能比等效对象类的效率还要低。

12. 使用iOS脚本调用优化功能

UnityEngine 命名空间中的函数的大多数是在 C/c + +中实现的。从Mono的脚本调用 C/C++函数也存在着一定的性能开销。您可以使用iOS脚本调用优化功能(菜单:Edit->Project Settings->Player)让每帧节省1-4毫秒。此设置的选项有:

Slow and Safe – Mono内部默认的处理异常的调用

Fast and Exceptions Unsupported –一个快速执行的Mono内部调用。不过,它并不支持异常,因此应谨慎使用。它对于不需要显式地处理异常(也不需要对异常进行处理)的应用程序来说,是一个理想的候选项。

13. 优化垃圾回收

如上文所述,您应该尽量避免分配操作。但是,考虑到它们是不能完全杜绝的,所以我们提供两种方法来让您尽量减少它们在游戏运行时的使用:

如果堆比较小,则进行快速而频繁的垃圾回收

这一策略比较适合运行时间较长的游戏,其中帧率是否平滑过渡是主要的考虑因素。像这样的游戏通常会频繁地分配小块内存,但这些小块内存只是暂时地被使用。如果在iOS系统上使用该策略,那么一个典型的堆大小是大约 200 KB,这样在iPhone 3G设备上,垃圾回收操作将耗时大约 5毫秒。如果堆大小增加到1 MB时,该回收操作将耗时大约 7ms。因此,在普通帧的间隔期进行垃圾回收有时候是一个不错的选择。通常,这种做法会让回收操作执行的更加频繁(有些回收操作并不是严格必须进行的),但它们可以快速处理并且对游戏的影响很小:

if (Time.frameCount % 30 == 0)

{

System.GC.Collect();

}

但是,您应该小心地使用这种技术,并且通过检查Profiler来确保这种操作确实可以降低您游戏的垃圾回收时间

如果堆比较大,则进行缓慢且不频繁的垃圾回收

这一策略适合于那些内存分配 (和回收)相对不频繁,并且可以在游戏停顿期间进行处理的游戏。如果堆足够大,但还没有大到被系统关掉的话,这种方法是比较适用的。但是,Mono运行时会尽可能地避免堆的自动扩大。因此,您需要通过在启动过程中预分配一些空间来手动扩展堆(ie,你实例化一个纯粹影响内存管理器分配的"无用"对象):

function Start() {

var tmp = new System.Object[1024];

// make allocations in smaller blocks to avoid them to be treated in a special way, which is designed for large blocks

for (var i : int = 0; i < 1024; i++)

tmp[i] = new byte[1024];

// release reference

tmp = null;

}

游戏中的暂停是用来对堆内存进行回收,而一个足够大的堆应该不会在游戏的暂停与暂停之间被完全占满。所以,当这种游戏暂停发生时,您可以显式请求一次垃圾回收:

System.GC.Collect();

另外,您应该谨慎地使用这一策略并时刻关注Profiler的统计结果,而不是假定它已经达到了您想要的效果。

C#程序员整理的Unity 3D笔记(三):Unity3D工具和VS 工具

      对于C#程序员而言,Visual Studio这个宇宙最牛的IDE肯定非常熟悉,编码、设计、代码着色等常用功能,用的还是很不错的,效率不是一般的高。本文就以VS IED作为参照物,进行和Unity IDE对比。

image    vs      image

 

 

Unity IDE

VS IDE

生产商

Unity科技(美国)

微软 (美国)

用户群体

游戏从业者

跨平台App开发者

.NET从业者(俗称微软阵营)

少数Web开发者

定价

Basic版本免费

Pro版本1500美金/平台

VS Express 免费

VS 2013 社区版免费

VS 旗舰版 3000美金

设计视图

有,且非常强大

代码视图

大纲视图

有 (视觉可见物体)

WinForm下无

Web开发有

属性视图

解决方案

独立文件夹(类似Eclipse)

*.sln

独立插件

场景

*.unity

程序集

*.exe、*.dll

亮点优势

游戏设计

跨平台

代码调试

UI控件

 

其中,在接触Unity 这个IDE后才知道,程序员仅仅编程是不够的,需要对各种模型(Model)、材质(Matrail)、纹理(Texture)要熟练掌握(导入、修改属性、3D空间内布局),同时还硬要了解一些物理学知识,如刚体、重力、碰撞。在Unity里面资源不叫Resource,而是叫Asset (好像任何东西在Unity都是这个称呼)。

GameObject和Component,GameObject是游戏对象,可独立操作的一个物体–一棵树或者一个人。 Componet是不见的,它类似GameObject的成员变量,游戏中90%的操作是控制GameObect的Component来完成的。

UI控件:Unity中的UI是我用过最难用的UI了,使用Winform开发的人可以很容易摆放UI控件、布局;但是在Unity中,只能代码控制。甚至难度超过Web中UI的布局,简直是毫无章法可依!呵呵,一下子UI回到解放前了。慢慢的,发现Unity中UI类似Web的流式渲染结构,从上往下、相对定位。

对Unity阵营而言,正在慢慢往C#方向迁移,如在Unity 5.0中,官方宣布要对默认的demo、文档用C#来写,要知道以前是JavaScript写的. (据不完全调查统计,Unity下C#脚本使用者占了7成比例)。同时,微软也在积极和Untiy靠近中,如今年年初收购了一家UnityVS插件欧洲公司,并免费对VS用户提供这个插件—有了这个插件用VS调试Unity 非常爽、非常爽。

VS开发的程序,无论是Winform还是Web,都有一定的规律可循,如通过事件响应触发函数。C#封装的几乎不用知道太多的细节—这个也是C#在VS下开发效率高的原因了。  而Unity下,采用的是游戏引擎驱动几个固定格式的函数按照游戏引擎一定的规律调用,函数之间,几乎完全靠全局变量来传递了–这个对OO编程而言比较不适应。我忙乎了1个月,Unity的Window UI还是没有能够掌握。 Start、Update等函数有起自身的规律,其内部的事件响应和注册有一些特殊的规律。

Unity里面有一个很酷的概念:时间。

 

Unity IDE

VS Winform

构造函数

Start

Construct

重绘函数

OnGUI

OnPaint (GUI+)

数学函数

Mathf

Math

驱动内核

时间驱动

事件驱动

Unity下之所以可以使用C#,一个很核心的原因是因为其内核在使用Mono.NET,一个不同于VS .NetFramework的C#。Mono是Linux下的,可移植的C#(截止本文写作,微软开源了其自己的.NET,貌似未来不久可使用.NEtFramework作为Unity的核心喽)

游戏开发有意思的地方是:其拟人化、寄托梦想的一个创新农场,容易上手、理解。

在多年开发中编码过的软件项目有3、5个,单个售价少的几万,多得上百万元人民币;但是,户数少的可怜,大多在几十个~几百之间,这个着实让我很不爽。啥时候可以开发上千人、上万人同时使用的软件系统,这个对我非常有意义。

Windows Live Writer出现Invalid response document returned from XmlRpc server错误的解决

比较啃的一个事件,替换了主题后,Windows Live Writer发不了博客了,通过下面的办法解决:

 

当Windows Live Writer在取回Wordpress平台建立的博客的日志(或页面),或者发布日志的时候出现如下错误对话框:

image

 

其中有如下的错误信息(如上图红色方框内文字):

Invalid response document returned from XmlRpc server

解决办法:

  1. 打开wordpress程序下的/wp-includes/class-IXR.php文件
  2. 找到字段:$length = strlen($xml);
  3. 将其替换为:$length = strlen($xml)+3;
  4. 保存即可

原因,据说是:因为wordpress本身的一个bug,在utf-8编码下,xmlrpc返回的格式不正确,缺了三个字节,所以那个字段后+3;也有说是因为wordpress的编码(utf-8)与Windows Live Writer(utf-8 +)编码不一样。

C#程序员整理的Unity 3D笔记(二)

学习Unity快一个月了,中间磕磕碰碰遇到了不少问题,好在是有几个小伙伴一起做,有讨论、分享的机会,不至于抓耳挠腮埋头苦做,废话不说了总结下这段时间的感悟。

关注:从去年Roger给我们几个介绍unity,自己也有意关注了些微信公众号、新闻之类的,猛然觉得c#还是能做好多东西,大家也不至于纠结C#前景不好,是否需转其他语言或平台等等。

动手:今年10月份开始真正动手,百度了一个别人做移动小车的例子,然后动手敲了一遍code,然后遇见了各种头大的事,比如transform是做什么的?Input怎么获取的变量?脚本怎么运行的?菜单在哪?别人的代码提供的不完整,有不知道缺失的是什么等等一系列问题。后面虽通过百度或其他途径解决了这些问题,总的感觉是自己太急功近利,反而是在走弯路,还是回到起点从基础知识看起,稳打稳扎的来,后面按yogi分享的打砖块例子,自己比葫芦画瓢也做了一个,感觉还是挺爽。

知识点

1.Camera :场景中包含多个camera时,想在预览时优先呈现某个视角时,把该camera的depth属性值设置为较大值(大于其他camera)

2.skybox:一种是全场景应用,一种是挂在camera上,随camera而变化,类似大家在同一个地图打怪,个人可以设置自己特有的背景画面

3.系统自带方法解释

void Awake () –初始化函数,在游戏开始时系统自动调用。一般用来创建变量之类的东西。

void Start() –初始化函数,在所有Awake函数运行完之后(一般是这样,但不一定),在所有Update函数前系统自动条用。一般用来给变量赋值。

void Update() –刷新函数,在游戏的每一帧都会调用。

void FixedUpdate() –以固定的频率,系统自动调用。

void LateUpdate() –在Update函数之后调用。

4.Instantiate生成物体方法中的第一个参数(物体对象),必须要在Inspector上指定,否则报一个空对象的错误

5.上周讨论时记录的几个问题,网上查阅的结果

/// 镜头离目标的距离

/// </summary>

public float Distance = 30.0f;

/// <summary>

/// 鼠标滚轮拉近拉远速度系数

/// </summary>

public float ScrollFactor = 10.0f;

//滚轮向前:拉近距离;滚轮向后:拉远距离

var scrollAmount = Input.GetAxis(GameSetting.MouseScrollWheel);

Distance -= scrollAmount * ScrollFactor;

 

//在攻击范围内:面朝玩家

var lookRotation = Quaternion.LookRotation(mTargetTransform.position – transform.position);

transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, RotateSpeed * Time.deltaTime);

6.VS2010/12不能挂脚本调试—原因之一建立的工程中未导入VS的资源包或reference中未设置为VS为调试工具

微软阵营企稳的利好消息:.NET开源、Visual Studio免费

今天,各个IT社区,头版头条说的是微软.NET开源了、宇宙中最好的IED–Visual Studio Community 2013将免费提供给用户的消息。

今天各个IT社区,头版头条说的是微软.NET开源了、宇宙中最好的IED–Visual Studio Community 2013将免费提供给用户的消息。

宇宙中最强大的开发环境免费了!

微软开放.NET框架源代码和Mono

微软宣布.NET开发环境将开源 支持Mac OS X和Linux

VS 开始支持 Android 和 iOS 编程,并自带 Android 模拟器

Mono for Unreal Engine发布,C#进入虚幻引擎(Unreal Engine) 》—今天刚翻译的infoQ文章

image

白天我忙于发布新产品《ActiveReports 9报表控件及报表服务器正式发布》,晚上得空翻翻新闻、思考思考微软阵营的一些可喜的变化:微软的云战略已经初具规模,目前考虑到linux系统运行微软云的比较多,故为了扩展.NET战略到其他系统中,因而开源了.NET,从而实现了10年前微软布局的“三屏一云”战略的核心—.NET纽带。微软现在的现金牛有XBox、Office、Azure、Windows、Visual Studio等

曾经预言,微软要使得自己的阵营江山稳固,需要做2件免费事情:

  • Visual Studio免费,学习Eclipse、学习XCode。
  • Windows免费,学习苹果的OX 10策略

目前看,VS免费已经成型,且随着Mono的.NET可移植性大放异彩,在Unity、Unreal游戏引擎方面也有斩获。

Xamarin明天会宣布集成到Visual Studio 2015中,作为默认模板,且微软已经表态,会在年底推出免费的Xamarin的东东, 这个对于使用C#开发跨平台的App是非常利好的消息。 同时,Visual Studio完美支持PhoneGap(Cordova)也使得VS开发跨平台的App稳固了阵营。

 

企业,玩生态圈的,先要弄点基础设施,别人无法超越的,稳固自己的阵脚,才有机会做大。

 

看看这些评论,.NET从业人员被JAVA压抑成啥玩意了!

image

 

image

C#程序员整理的Unity 3D笔记(一)

1. Horizontal 水平轴,Vertical 垂直位移,它们只是一个增量,取值的范围为-1到1.

2. Mouse X 鼠标水平移动,代码如下

this.transform.Translate(condition * Time.deltaTime * multiple, 0, 0)

3. Mouse Y 鼠标垂直垂直移动 ,代码如下

4. this.transform.Rotate(Vector3.left, condition * 10);

5. 物体朝向某个物体的方位this.transform.LookAt(transform);

6. Camera 中的Depth参数表示摄像机的视角,其中数值较大的在数值较小的上面(即Y值较大)

7. Camera clip_image002的属性代表视角度的范围,范围以外的视角是黑色

8. Camera 的Audio Listener 表示耳朵,可以监听目标发出的声音

9. Mesh 网格是用来建造复杂的GameObject,比如坦克,汽车等

10. Material 材质,表示GameObject的物理属性

11. Texture 纹理,表示GameObject表面是啥样子

12. Render Setting 设置整个Scene的天空盒子,Compont–>Rendering—>Skybox设置摄像机的天空盒子,摄像机的天空盒子优先级高于Scene的,勾选Fog设置雾效果

13. Material–>Inspector视图—-> RenderFX—-> SkyBox 自制天空盒子,自制天空盒子的材料将Warp Mode 设置成Damp可以无缝连接六张图片

14. GameObject 的Mesh Render属性控制游戏场景中物体的可见性,勾选Static属性,可以使物体不会移动

15. this.transform.TransformPoint可以将坐标点从Local—> world

16. this.transform.InverseTransformDirection以将坐标点从world —> Local

17. this.transform.TransformDirection方向从Local—> world

18. this.transform.InverseTransformDirection方向从world —> Local

19. GUI中屏幕坐标系以左上角为原点,右下角为(Screen.Width,Screen.Height)

20. GUILayout直接控制全部控件的样式,类似Js中的CSS