unity实现unity3d 物体移动轨迹旋转要求速度轨迹曲线为cos,最大速度不超过90度每秒,当

【Unity技巧】四元和旋转_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
【Unity技巧】四元和旋转
上传于|0|0|文档简介
&&【Unity技巧】四元和旋转
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩1页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢2243人阅读
unity3d(4)
&&偶然在群里看到有人拿了一张椭圆物体旋转选择界面来问怎么实现(也不知道这样描述对不对,反正是椭圆的,而且还是旋转的,类似于关卡和角色选择),于是
想了下自己写了一个类似的功能,方法可能不是很完美,但是也算是一个思路吧,就当练练手熟悉unity。原图如下:
附自己完成后的效果图:
遗憾的是不会做动态图片,也不知道大神写博客是怎么弄运行代码时的动态效果图,只能附上渣渣图片了~
基本效果能够达到一致,但是只是直接移动,原本是想实现绕椭圆轨迹移动,这里不得不说,unity动作机制几乎没有,原本api就难找,自己找半天连一个move的函
数都没有,如果不去找一个插件,只能通过update每一帧去手动设置GameObject的位置来达到move的效果,原本我以为是能够像cocos那样,最起码,moveto,得有,
然后用贝塞尔模拟,可惜只能每帧刷新的话就先不写了。
方块的摆布:
首先需要明确的是方块的排布问题,摆布有多种方式,可以先将所有的方块保存到容器,之后按照一定的坐标差值来递增,递减这些方块的摆放位置,最后达到
该视觉效果,只是在排列的过程中需要长时间的调试效果,因而没有采用;同时也可以按照椭圆的轨迹来摆放,根据对象容器的遍历,每次递增或递减一定角度
达到该效果,这个方式是比较方便的,只需要根据当前角度偏移量来计算出方块对应的位置即可。当然,我们还需要考虑方块的奇偶性,在方块为奇数时,除去
第一个显示在正中央的方块,刚好还剩下偶数个方块,左右正好排布一半,但是当方块为偶数个时,除去第一个,还会剩下最后一个方块。
方块为奇数时: & & &该情况较为简单,除去第一个,剩下的刚好对半分成,可以这样考虑:将所有需要排布的方块Object存放到一个数组sprites里边,取size=(length+1)/2
例如有七个方块,前边size个(四个)从中间开始往右递增排布,即保证容器前size个是顺次排布,剩下三个从中间(除去中间那个点)往左边排布。
方块为偶数时: & & &该情况稍微复杂一点,除去第一个,再分去左右对称的,还会多出一个来,可以这样考虑:将所有方块存放到一个数组sprites里,取size=length/2
例如有八个方块,前边size个(四个)从中间开始往右递增排布,剩下三个从中间(除去中间那个点)往左边排布,最后一个可以放到第一个的正对面。
显示层级: &在cocos2dx中,子类节点都是通过挂载到父节点的形式添加到场景中,在addchild的时候提供一个zorder参数,即精灵的渲染层级,而
unity不同,查找api找了半天,最后找到SetSiblingIndex函数,值越大越后显示,没次初始化和移动都必须重置显示层级,所以需要单独封装函数。
点击按钮之后的回调
向左按钮:点击向左按钮时,右边的方块同一往左移一格位置,左边的方块统一往上移一格位置,左边最后一个方块移动到右边最后一个方块向右按钮:同理。
开始动手开发
新建项目:2d,3d无所谓,这里是3d,但是要用一般是在2d,只是项目而已。添加控件:首先添加七个Image对象(控件可以是按钮,都行);添加left和right的button,摆布没有要求,随意摆放,反正都是要做排序的。如图:(这里panel是没必要的,我多加的)
&添加UI按椭圆顺序排布脚本
新建脚本:Ellipse.cs脚本,对象绑定到Canvas对象。编写代码: &//保存需要排序的精灵容器
public GameObject[] S
public Transform centerP//椭圆的中心点
public float anglecheap = 25;//每个方块间的角度偏移
//保存位置点
private List&Vector3& location = new List&Vector3&();
private float angle =270;//第一个保证是中心位置的,当前到的角度
private float firstangle = 270;//记录第一个角度,用以左右对称
private float r =90;//椭圆的两个弦长
private float R = 150;
  int size = 0;//即对象数组的一半,奇数为总长度+1/2,偶数为一半&pre name=&code& class=&csharp&&// Use this for initialization
void Start ()
{//初始化size
if (Sprites.Length % 2 == 0)
size = Sprites.Length / 2;
size = (Sprites.Length + 1) / 2;
//排序分级显示
makespriteSort();
//重置渲染层级
ResetDeep();
//给这些精灵排序显示
void makespriteSort()
//取出椭圆的中心点
Vector3 center = centerPoint.
//判断该数组的个数奇偶性,如果是偶数,那么需要留出一个来放到对面
if (Sprites.Length % 2 == 0)
for (int i = 0; i & i++)
Sprites[i].transform.position = getPosition(angle, center);
m_rightsprite.Add(Sprites[i]);
//第一个已经得是左边了
angle = firstangle -
for (int i = i & Sprites.Length-1; i++)
Sprites[i].transform.position = getPosition(angle, center);
m_leftsprite.Add(Sprites[i]);
//最后一个
Sprites[Sprites.Length - 1].transform.position = getPosition(firstangle-180, center);
// m_leftsprite.Add(Sprites[Sprites.Length - 1]);
//如果不是偶数,那么出去中间那个,正好正常显示
for (int i = 0;i& i++)
Sprites[i].transform.position = getPosition(angle, center);
m_rightsprite.Add(Sprites[i]);
//第一个已经得是左边了
angle = firstangle -
for (int i =i & Sprites.L i++)
Sprites[i].transform.position = getPosition(angle, center);
m_leftsprite.Add(Sprites[i]);
//获取当前角度的坐标
Vector3 getPosition(float _angle,Vector3 _centerposition)
float hudu = (_angle/180f) * Mathf.PI;
float cosx = Mathf.Cos(hudu);
float sinx = Mathf.Sin(hudu);
float x = _centerposition.x + R *
float y = _centerposition.y + r *
Vector3 point = new Vector3(x, y, 0);
//添加到容器保存
location.Add(point);
//根据当前左右容器调整所有控件的渲染层级
void ResetDeep()
for (int i =size-1; i&=0; i--)
Sprites[i].GetComponent&Transform&().SetSiblingIndex(dep);
for (int i = Sprites.Length - 1; i &= i--)
Sprites[i].GetComponent&Transform&().SetSiblingIndex(dep);
}运行后可以看到如图效果(不要忘了把这几个对象拖到脚本里,中心点是传入的对象,所以有一个位置要摆好,摆在想要的中心点中,也可以自己改成手动输入x,y,z):
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:36323次
排名:千里之外
原创:25篇
转载:10篇
(4)(1)(5)(1)(1)(2)(4)(2)(1)(5)(1)(4)(3)(1)(1)此总结由自己经验及网上收集整理优化内容 包括:1.代码方面;2.函数使用方面;3.ngui注意方面;4.数学运算方面;5.内存方面;6.垃圾回收方面 等等...本着相互交流 共同进步的原则希望大家看后 有其他或者更好的优化方案 欢迎跟帖。好了,总结如下:1. 尽量避免每帧处理,可以每隔几帧处理一次比如:[C#] 纯文本查看 复制代码function Update() { DoSomeThing(); }可改为每5帧处理一次:[C#] 纯文本查看 复制代码function Update() { if(Time.frameCount % 5 == 0) { DoSomeThing(); } }2. 定时重复处理用InvokeRepeating 函数实现比如,启动0.5秒后每隔1秒执行一次 DoSomeThing 函数:[C#] 纯文本查看 复制代码function Start() { InvokeRepeating("DoSomeThing", 0.5, 1.0); }
CancelInvoke("你调用的方法"); 停止InvokeRepeating3. 优化 Update,FixedUpdate, LateUpdate 等每帧处理的函数,函数里面的变量尽量在头部声明。比如:[C#] 纯文本查看 复制代码function Update() { var pos: Vector3 = transform. }可改为[C#] 纯文本查看 复制代码private var pos: Vector3; function Update(){ pos = transform. }4. 主动回收垃圾给某个 GameObject 绑上以下的代码:[C#] 纯文本查看 复制代码function Update() { if(Time.frameCount % 50 == 0) { System.GC.Collect(); } }5. 运行时尽量减少 Tris 和 Draw Calls预览的时候,可点开 Stats,查看图形渲染的开销情况。特别注意 Tris 和 Draw Calls 这两个参数。一般来说,要做到:Tris 保持在 7.5k 以下Draw Calls 保持在 35 以下6. 压缩 Mesh导入 3D 模型之后,在不影响显示效果的前提下,最好打开 Mesh Compression。Off, Low, Medium, High 这几个选项,可酌情选取。对于单个Mesh最好使用一个材质。7. 避免大量使用
自带的 Sphere 等内建 MeshUnity 内建的 Mesh,多边形的数量比较大,如果物体不要求特别圆滑,可导入其他的简单3D模型代替。8. 优化数学计算尽量避免使用float,而使用int,特别是在中,尽量少用复杂的数学函数,比如sin,cos等函数。改除法/为乘法,例如:使用x*0.5f而不是 x/2.0f 。9.如果你做了一个图集是的。此时你的界面上只用了图集中的一张很小的图,那么很抱歉这张大图都需要载入你的内存里面,1024就是4M的内存,如果你做了10个1024的图集,你的界面上刚好都只用了每个图集里面的一张小图,那么再次抱歉你的内存直接飙40M。意思是任何一个4096的图片,不管是图集还是texture,他都占用4*4=16M?====================================================================分割线=====================================================1、在使用数组或ArrayList对象时应当注意本帖隐藏的内容[C#] 纯文本查看 复制代码length=myArray.L
for(int i=0;i&i++)
}避免[C#] 纯文本查看 复制代码for(int i=0;i&myArray.Li++)
}2、少使用临时变量,特别是在Update OnGUI等实时调用的函数中。[C#] 纯文本查看 复制代码void Update()
pos=transform.
}可以改为:[C#] 纯文本查看 复制代码private Vector3
void Update()
pos=transform.
3、如果可能,将GameObject上不必要的脚本disable掉。如果你有一个大的场景在你的游戏中,并且敌方的位置在数千米意外,这时你可以disable你的敌方AI脚本直到它们接近摄像机为止。一个好的途径来开启或关闭GameObject是使用SetActiveRecursively(false),并且球形或盒型碰撞器设为trigger。4、删除空的Update方法。当通过Assets目录创建新的脚本时,脚本里会包括一个Update方法,当你不使用时删除它。5、引用一个游戏对象的最合乎逻辑的组件。有人可能会这样写someGameObject.transform,gameObject.rigidbody.transform.gameObject.rigidbody.transform,但是这样做了一些不必要的工作,你可以在最开始的地方引用它,像这样:[C#] 纯文本查看 复制代码privateTransform myT
void Start()
}6、协同是一个好方法。可以使用协同程序来代替不必每帧都执行的方法。(还有InvokeRepeating方法也是一个好的取代Update的方法)。7、尽可能不要再Update或FixedUpdate中使用搜索方法(例如GameObject.Find()),你可以像前面那样在Start方法里获得它。8、不要使用SendMessage之类的方法,他比直接调用方法慢了100倍,你可以直接调用或通过C#的委托来实现。9、使用javascript或Boo语言时,你最好确定变量的类型,不要使用动态类型,这样会降低效率,你可以在脚本开头使用#pragmastrict 来检查,这样当你编译你的游戏时就不会出现莫名其妙的错误了。====================================================================分割线=====================================================1、顶点性能
一般来说,如果您想在iPhone 3GS或更新的设备上每帧渲染不超过40,000可见点,那么对于一些配备 MBX GPU的旧设备(比如,原始的 iPhone,如 iPhone 3g和 iPod Touch第1和第2代)来说,你应该保证每帧的渲染顶点在10000以下。2、光照性能
像素的动态光照将对每个受影响的像素增加显著的计算开销,并可能导致物体会被渲染多次。为了避免这种情况的发生,您应该避免对于任何单个物体都使用多个像素光照,并尽可能地使用方向光。需要注意的是像素光源是一个渲染模式(Render Mode)设置为重要(Important)的光源。像素的动态光照将对顶点变换增加显著的开销。所以,应该尽量避免任何给定的物体被多个光源同时照亮的情况。对于静态物体,采用烘焙光照方法则是更为有效的方法。3、角色
每个角色尽量使用一个Skinned Mesh Renderer,这是因为当角色仅有一个 Skinned Mesh Renderer 时,Unity 会使用可见性裁剪和包围体更新的方法来优化角色的运动,而这种优化只有在角色仅含有一个 Skinned Mesh Renderer时才会启动。角色的面数一般不要超过1500,骨骼数量少于30就好,角色Material数量一般1~2个为最佳。4、静态物体
对于静态物体定点数要求少于500,UV的取值范围不要超过(0,1)区间,这对于纹理的拼合优化很有帮助。不要在静态物体上附加Animation组件,虽然加了对结果没什么影响,但是会增加CPU开销。5、摄像机
将远平面设置成合适的距离,远平面过大会将一些不必要的物体加入渲染,降低效率。另外我们可以根据不同的物体来设置摄像机的远裁剪平面。Unity 提供了可以根据不同的 layer 来设置不同的 view distance ,所以我们可以实现将物体进行分层,大物体层设置的可视距离大些,而小物体层可以设置地小些,另外,一些开销比较大的实体(如粒子系统)可以设置得更小些等等。6、DrawCall
尽可能地减少 Drawcall 的数量。 IOS 设备上建议不超过 100 。减少的方法主要有如下几种: Frustum Culling ,Occlusion Culling , Texture Packing 。 Frustum Culling 是 Unity 内建的,我们需要做的就是寻求一个合适的远裁剪平面;Occlusion Culling ,遮挡剔除, Unity 内嵌了 Umbra ,一个非常好 OC 库。但 Occlusion Culling 也并不是放之四海而皆准的,有时候进行 OC 反而比不进行还要慢,建议在 OC 之前先确定自己的场景是否适合利用 OC 来优化; Texture Packing ,或者叫 Texture Atlasing ,是将同种 shader 的纹理进行拼合,根据 Unity 的 static batching 的特性来减少 draw call 。建议使用,但也有弊端,那就是一定要将场景中距离相近的实体纹理进行拼合,否则,拼合后很可能会增加每帧渲染所需的纹理大小,加大内存带宽的负担。这也就是为什么会出现“ DrawCall 降了,渲染速度也变慢了”的原因。===========================================分割线==========================1.粒子系统运行在iPhone上时很慢,怎么办?答:iPhone拥有相对较低的fillrate 。如果您的粒子效果覆盖大部分的屏幕,而且是multiple layers的,这样即使最简单的shader,也能让iPhone傻眼。我们建议把您的粒子效果baking成纹理序列图。然后在运行时可以使用1-2个粒子,通过动画纹理来显示它们。这种方式可以取得很好的效果,以最小的代价。
===========================================分割线==============================1.操作transform.localPosition的时候请小心移动GameObject是非常平常的一件事情,以下代码看起来很简单:[C#] 纯文本查看 复制代码transform.localPosition += new Vector3 ( 10.0f * Time.deltaTime, 0.0f, 0.0f );但是小心了,假设上面这个GameObject有一个parent, 并且这个parent GameObject的localScale是(2.0f,2.0f,2.0f)。你的GameObject将会移动20.0个单位/秒。因为该 GameObject的world position等于:[C#] 纯文本查看 复制代码Vector3 offset = new Vector3( my.localPosition.x * parent.lossyScale.x, my.localPosition.y * parent.lossyScale.y, my.localPosition.z * parent.lossyScale.z );Vector3 worldPosition = parent.position + parent.rotation *换句话说,上面这种直接操作localPosition的方式是在没有考虑scale计算的时候进行的,为了解决这个,提供了Translate函数,所以正确的做法应该是: [C#] 纯文本查看 复制代码transform.Translate ( 10.0f * Time.deltaTime, 0.0f, 0.0f );曝出在Inspector的变量同样的也能被Animation View Editor所使用有时候我们会想用Unity3D自带的Animation View Editor来做一些简单的动画操作。而Animation Editor不仅可以操作Unity3D自身的component,还可以操作我们自定义的MonoBehavior中的各个Property。所以加入 你有个float值需要用曲线操作,你可以简单的将它曝出到成可以serialize的类型,如:[C#] 纯文本查看 复制代码public float foobar = 1.0f;这样,这个变量不仅会在Inspector中出现,还可以在animation view中进行操作,生成AnimationClip供我们通过AnimationComponent调用。范例:[C#] 纯文本查看 复制代码public class TestCurve : MonoBehaviour
public float foobar = 0.0f;
IEnumerator Start ()
yield return new WaitForSeconds (2.0f);
animation.Play("foobar_op");
InvokeRepeating ( "LogFoobar", 0.0f, 0.2f );
yield return new WaitForSeconds (animation["foobar_op"].length);
CancelInvoke ("LogFoobar");
void LogFoobar ()
Debug.Log("foobar = " + foobar); }}2.GetComopnent&T& 可以取父类类型Unity3D 允许我们对MonoBehavior做派生,所以你可能有以下代码:[C#] 纯文本查看 复制代码public class foo : MonoBehaviour { ...} public class bar : foo { ...}假设我们现在有A,B两个GameObject, A包含foo, B包含bar, 当我们写[C#] 纯文本查看 复制代码foo comp1 = A.GetComponent&foo&();bar comp2 = B.GetComponent&bar&();可以看到comp1, comp2都得到了应得的Component。那如果我们对B的操作改成:[C#] 纯文本查看 复制代码foo comp2 = B.GetComponent&foo&();答案是comp2还是会返回bar Component并且转换为foo类型。你同样可以用向下转换得到有效变量:bar comp2_bar = comp2合理利用GetComponent&base_type&()可以让我们设计Component的时候耦合性更低。3.Invoke, yield 等函数会受 Time.timeScale 影响Unity3D提供了一个十分方便的调节时间的函数Time.timeScale。对于初次使用Unity3D的使用者,会误导性的认为Time.timeScale同样可以适用于游戏中的暂停(Pause)和开始(Resume)。所以很多人有习惯写:[C#] 纯文本查看 复制代码Time.timeScale = 0.0f对于游戏的暂停/开始,是游戏系统设计的一部分,而Time.timeScale不不是用于这个部分的操作。正确的做法应该是搜集需要暂停的脚本或 GameObject,通过设置他们的enabled = false 来停止他们的脚本活动或者通过特定函数来设置这些物件暂停时需要关闭那些操作。Time.timeScale 更多的是用于游戏中慢镜头的播放等操作,在服务器端主导的游戏中更应该避免此类操作。值得一提的是,Unity3D的许多时间相关的函数都和 timeScale挂钩,而timeScale = 0.0f将使这些函数或动画处于完全停止的状态,这也是为什么它不适合做暂停操作的主要原因。这里列出受timeScale影响的一些主要函数和Component:MonoBehaviour.Invoke(…)MonoBehaviour.InvokeRepeating(…)yield WaitForSeconds(…)GameObject.Destroy(…)Animation ComponentTime.time, Time.deltaTime…4.Coroutine 和 IEnumerator的关系初写Unity3D C#脚本的时候,我们经常会犯的错误是调用Coroutine函数忘记使用StartCoroutine的方式。如:TestCoroutine.cs[C#] 纯文本查看 复制代码IEnumerator CoLog () { yield return new WaitForSeconds (2.0f); Debug.Log("hello foobar");}当我们用以下代码去调用上述函数:[C#] 纯文本查看 复制代码TestCoroutine testCo = GetComponent&TestCoroutine&();testCo.CoLog ();testCo.StartCoroutine ( "CoLog" );那么testCo.CoLog()的调用将不会起任何作用。5.StartCoroutine, InvokeRepeating 和其调用者关联通常我们只在一份GameObject中去调用StartCoroutine或者InvokeRepeating,我们写:[C#] 纯文本查看 复制代码StartCoroutine ( Foobar() );InvokeRepeating ( "Foobar", 0.0f, 0.1f );所以如果这个GameObject被disable或者destroy了,这些coroutine和invokes将会被取消。就好比我们手动调用:[C#] 纯文本查看 复制代码StopAllCoroutines ();CancelInvoke ();这看上去很美妙,对于AI来说,这就像告诉一个NPC你已经死了,你自己的那些小动作就都听下来吧。但是注意了,假如这样的代码用在了一个Manager类型的控制AI上,他有可能去控制其他的AI, 也有可能通过Invoke, Coroutine去做一些微线程的操作,这个时候就要明确StartCoroutine或者InvokeRepeating的调用者的设计。讨论之前我 们先要理解,StartCoroutine或InvokeRepeating的调用会在该MonoBehavior中开启一份Thread State, 并将需要操作的函数,变量以及计时器放入这份Stack中通过并在引擎每帧Update的最后,Renderer渲染之前统一做处理。所以如果这个 MonoBehavior被Destroy了,那么这份Thread State也就随之消失,那么所有他存储的调用也就失效了。如果有两份GameObject A和B, 他们互相知道对方,假如A中通过StartCoroutine或InvokeRepeating去调用B的函数从而控制B,这个时候Thread State是存放在A里,当A被disable或者destroy了,这些可能需要一段时间的控制函数也就失效了,这个时候B明明还没死,也不会动了。更 好的做法是让在A的函数中通过B.StartCoroutine ( … ) 让这份Thread State存放于B中。[C#] 纯文本查看 复制代码// class TestCortouine
public class TestCoroutine : MonoBehaviour
public IEnumerator CoLog ( string _name )
Debug.Log(_name + " hello foobar 01");
yield return new WaitForSeconds (2.0f);
Debug.Log(_name + " hello foobar 02"); }}
// component attached on GameObject A
public class A: MonoBehaviour
public GameObject B;
void Start ()
{ TestCoroutine compB = B.GetComponent&TestCoroutine&();
// GOOD, thread state in B
// same as: comp
B.StartCoroutine ( "CoLog", "B" );
compB.StartCoroutine ( compB.CoLog("B") );
// BAD, thread state in A
StartCoroutine ( compB.CoLog("A") );
Debug.Log("Bye bye A, we'll miss you");
Destroy(gameObject);
// T_T I don't want to die... }}以上代码,得到的结果将会是:B hello foobar 01A hello foobar 01Bye bye A, we'll miss youB hello foobar 02如不需要Start, Update, LateUpdate函数,请去掉他们当你的脚本里没有任何Start, Update, LateUpdate函数的时候,Unity3D将不会将它们加入到他的Update List中,有利于脚本整体效率的提升。我们可以从这两个脚本中看到区别:Update_01.cs[C#] 纯文本查看 复制代码public class Update_01 : MonoBehaviour { void Start () {} void Update () {}}Update_02.cs[C#] 纯文本查看 复制代码public class Update_02 : MonoBehaviour {
}===========================================分割线==============1.减少固定增量时间将固定增量时间值设定在0.04-0.067区间(即,每秒15-25帧)。您可以通过Edit-&Project Settings-&Time来改变这个值。这样做降低了FixedUpdate函数被调用的频率以及物理引擎执行碰撞检测与刚体更新的频率。如果您使用了较低的固定增量时间,并且在主角身上使用了刚体部件,那么您可以启用插值办法来平滑刚体组件。2.减少GetComponent的调用使用 GetComponent或内置组件访问器会产生明显的开销。您可以通过一次获取组件的引用来避免开销,并将该引用分配给一个变量(有时称为"缓存"的引用)。例如,如果您使用如下的代码:[JavaScript] 纯文本查看 复制代码function Update ()
transform.Translate(0, 1, 0);
}通过下面的更改您将获得更好的性能:[JavaScript] 纯文本查看 复制代码var myTransform : T
function Awake () {
myTransform =
function Update () {
myTransform.Translate(0, 1, 0);
}3.避免分配内存您应该避免分配新对象,除非你真的需要,因为他们不再在使用时,会增加垃圾回收系统的开销。您可以经常重复使用数组和其他对象,而不是分配新的数组或对象。这样做好处则是尽量减少垃圾的回收工作。同时,在某些可能的情况下,您也可以使用结构(struct)来代替类(class)。这是因为,结构变量主要存放在栈区而非堆区。因为栈的分配较快,并且不调用垃圾回收操作,所以当结构变量比较小时可以提升程序的运行性能。但是当结构体较大时,虽然它仍可避免分配/回收的开销,而它由于"传值"操作也会导致单独的开销,实际上它可能比等效对象类的效率还要低。4.最小化GUI使用GUILayout 函数可以很方便地将GUI元素进行自动布局。然而,这种自动化自然也附带着一定的处理开销。您可以通过手动的GUI功能布局来避免这种开销。此外,您也可以设置一个脚本的useGUILayout变量为 false来完全禁用GUI布局:[JavaScript] 纯文本查看 复制代码function Awake () {
useGUILayout =
}5.使用iOS脚本调用优化功能UnityEngine 命名空间中的函数的大多数是在 C/c + +中实现的。从Mono的脚本调用 C/C++函数也存在着一定的性能开销。您可以使用iOS脚本调用优化功能(菜单:Edit-&Project Settings-&Player)让每帧节省1-4毫秒。此设置的选项有:Slow and Safe – Mono内部默认的处理异常的调用Fast and Exceptions Unsupported –一个快速执行的Mono内部调用。不过,它并不支持异常,因此应谨慎使用。它对于不需要显式地处理异常(也不需要对异常进行处理)的应用程序来说,是一个理想的候选项。6.优化垃圾回收如上文所述,您应该尽量避免分配操作。但是,考虑到它们是不能完全杜绝的,所以我们提供两种方法来让您尽量减少它们在游戏运行时的使用:如果堆比较小,则进行快速而频繁的垃圾回收这一策略比较适合运行时间较长的游戏,其中帧率是否平滑过渡是主要的考虑因素。像这样的游戏通常会频繁地分配小块内存,但这些小块内存只是暂时地被使用。如果在iOS系统上使用该策略,那么一个典型的堆大小是大约 200 KB,这样在iPhone 3G设备上,垃圾回收操作将耗时大约 5毫秒。如果堆大小增加到1 MB时,该回收操作将耗时大约 7ms。因此,在普通帧的间隔期进行垃圾回收有时候是一个不错的选择。通常,这种做法会让回收操作执行的更加频繁(有些回收操作并不是严格必须进行的),但它们可以快速处理并且对游戏的影响很小:[C#] 纯文本查看 复制代码if (Time.frameCount % 30 == 0)
System.GC.Collect();
}但是,您应该小心地使用这种技术,并且通过检查Profiler来确保这种操作确实可以降低您游戏的垃圾回收时间如果堆比较大,则进行缓慢且不频繁的垃圾回收这一策略适合于那些内存分配 (和回收)相对不频繁,并且可以在游戏停顿期间进行处理的游戏。如果堆足够大,但还没有大到被系统关掉的话,这种方法是比较适用的。但是,Mono运行时会尽可能地避免堆的自动扩大。因此,您需要通过在启动过程中预分配一些空间来手动扩展堆(ie,你实例化一个纯粹影响内存管理器分配的"无用"对象):[JavaScript] 纯文本查看 复制代码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 = new byte[1024];
// release reference
}游戏中的暂停是用来对堆内存进行回收,而一个足够大的堆应该不会在游戏的暂停与暂停之间被完全占满。所以,当这种游戏暂停发生时,您可以显式请求一次垃圾回收:System.GC.Collect();另外,您应该谨慎地使用这一策略并时刻关注Profiler的统计结果,而不是假定它已经达到了您想要的效果。
如果您想留下此文,您可以将其发送至您的邮箱(将同时以邮件内容&PDF形式发送)
相关文章推荐
(Ctrl+Enter提交) &&
已有0人在此发表见解
&在& 17:15收藏到了
&&在信息爆炸的时代,您的知识需要整理,沉淀,积累!Lai18为您提供一个简单实用的文章整理收藏工具,在这里您可以收藏对您有用的技术文章,自由分门别类,在整理的过程中,用心梳理自己的知识!相信,用不了多久,您收藏整理的文章将是您一生的知识宝库!
· 蜀ICP备号-1

我要回帖

更多关于 unity 轨迹动画 的文章

 

随机推荐