重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
今天小编给大家分享一下Unity代码层优化和规避的方法有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
目前创新互联建站已为上1000家的企业提供了网站建设、域名、虚拟主机、网站托管、服务器租用、企业网站设计、灵台网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
1.尽可能少用不用循环逻辑精简循环主体代码(While,for,foreach,递归)
在业务需求层面能避免循环逻辑的时候尽量避免,确实是需要循环逻辑的话就把逻辑理清楚,主要循环体的代码不能有任何多余的变量或者多余内存占用。另外:
for(int i=0;i2.巧用生命周期函数Update和LateUpdata。
明确每一帧Updata和固定帧LateUpdata的函数意义,在使用两者的时候要明确当前需求是否要高频率的执行调用,如果确实需要每一帧都执行调用或者在单帧上进行逻辑处理(比如画面渲染等)那我们就用到Updata;另外如果我们对刷新执行的频率要求不高(比如物理的位移旋转等逻辑)我们就可以用到LateUpdata;删除空的Update方法
void Update() { if (isTrue) { isTrue = false;}//一定要加条件保护 } private void LateUpdate() { transform.Rotate(Vector3.up * Time.fixedDeltaTime * speed); }3.只在变化发生时才去执行代码(UI界面数据刷新)。
很多时候的逻辑我们都是不用特殊处理时时关照的,比如UI界面的数据刷新,很多初学者喜欢把ui的刷新逻辑直接扔在Updata里面,这样虽然很省事我们不必再单独的对界面数据的管理和维护,但是界面如果数据量大,更新频繁这时候对程序就造成很大的渲染负担,我们可以通过使用委托等方法只有在有数据更新的时候调用ui的界面刷新逻辑
public delegate void MyDelegate(int score);//定义委托 public MyDelegate myDelegate; //声明委托 private int score = 0; public int Score { get => score; set { score = value; myDelegate?.Invoke(score); } } private void Start() { myDelegate += UpdataUIData;//委托注册事件 } public void UpdataUIData(int score) { //刷新ui界面数据 }4.将需要频繁执行且不能通过事件触发的方法改为每隔几帧执行一次。比如刚才说的lateUpdata固定帧。除去这个外我们还可以灵活运用协同,在一开始的时候就开启一个协同
private void Start() { InvokeRepeating("RunSomeThing",1,5);//一秒钟执行五次 } private int interval = 3;//间隔帧 void Update() { if (Time.frameCount % interval == 0)//每三帧执行一次 { RunSomeThing(); } } public void RunSomeThing() { }5.使用缓存存储需要反复获取和使用的值。
.动态获取的组件可以存储到全局变量中,使用的时候直接取避免了反复获取
.反复使用的临时变量,声明的时候我们就可以放到全局存储起来
.动态实例化出来的对象,我们要想办法给管理起来方便下次直接使用6.数值类型尽量避免使用float,而使用int,特别是在手机游戏中,尽量少用复杂的数学函数,比如sin,cos等函数。改除法/为乘法,例如:使用x*0.5f而不是 x/2.0f 。
7.主动进行垃圾回收
void Update() { //固定时间GC回收但也不能太频繁,建议跳转场景的时候或者重要模块切换的时候回收 if (Time.frameCount % 50 == 0) { GC.Collect(); } }二:避免调用高开销的Unity API
1. SendMessage()和BroadcastMessage()使用了反射而反射会造成更多的CPU开销。你可以直接调用或通过C#的委托来实现。
2. Find()方法会遍历内存中的每个GameObject和组件,随着项目规模的扩张,它的开销将会越来越大。避免使用Find()和与其类似的方法,尽可能不要再Update或FixedUpdate中使用搜索方法
3.Transform中设置position和rotation会触发内部的OnTransformChanged事件并传播到所有的子级对象中,对于含有非常对子物体的对象来说,这种操作开销很大,应该 减少对position和rotation的修改。如果某个方法中要分别设置position的xyz,可以创建一个Vector3然后分别将xyz设置到该Vector3中,最后将Vector3设置给position,而不要每次分开设置position的xyz。尝试使用localPosition替代position。localPosition存储在transform中,访问该值时,Unity会直接将其返回,而position在每次访问时都会重新计算,如果要经常获取position,可以将其缓存起来。
4.Update()和LateUpdate()等事件方法的每次调用都需要引擎代码与托管代码之间进行通信,还要Unity进行安全检查(GameObject状态是否合法等),即使这些事件方法的方法体是空的,引擎任然会对其进行调用。因此,为避免浪费CPU时间,应该 删除空的事件方法。另外,如果某个活动状态(gameObject.active == true)的GameObject上的脚本中含有Awake()方法,即使这个脚本没有被启用(enabled==false),Awake()方法也会执行。如果游戏中含有非常多的带有Update()方法的MonoBehavior,应该尝试改变代码结构来减少开销,这有一篇相关的博客。
5.Vector2和Vector3()向量的数学运算要比普通的浮点数和整数的数学运算更加复杂,访问向量的某些属性可能会带来隐含的开销,例如magnitude属性(不仅针对向量,例如上文提到的Transform.position)。每次访问magnitude,引擎都会进行开平方运算,虽然单次计算并不会消耗多少时间, 但当数量级足够大时,这种开销将变得明显。可以尝试使用sqrMagnitude(即magnitude的平方)替代magnitude,减少开平方操作。
6.Camera.main所引起的问题与Find()方法类似,应该避免使用Camera.main并且手动管理对相机的引用。
以上就是“Unity代码层优化和规避的方法有哪些”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注创新互联行业资讯频道。
网页题目:Unity代码层优化和规避的方法有哪些
链接地址:http://cqcxhl.cn/article/gdheig.html