温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Unity代码层优化和规避的方法有哪些

发布时间:2022-10-24 11:32:50 来源:亿速云 阅读:151 作者:iii 栏目:移动开发

今天小编给大家分享一下Unity代码层优化和规避的方法有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

一:提升代码效率

1.尽可能少用不用循环逻辑精简循环主体代码(While,for,foreach,递归)

在业务需求层面能避免循环逻辑的时候尽量避免,确实是需要循环逻辑的话就把逻辑理清楚,主要循环体的代码不能有任何多余的变量或者多余内存占用。另外:

for(int i=0;i<myArray.Length;i++)//避免

int length=myArray.Length;  
for(int i=0;i<length;i++) //提倡

2.巧用生命周期函数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代码层优化和规避的方法有哪些”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

向AI问一下细节
推荐阅读:
  1. Unity优化
  2. unity优化笔记

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI