什么是DrawCall,有什么方法可以减少DrawCall?

2020-04-20 09:31发布

7条回答

楼上几位已经把概念描述的很标准了,这里如果楼主还是没看明白我给你举个生活中的例子。

可以这么理解你问的这个概念:你现在饿了来到一个餐馆要吃饭,而你自己本身不会做饭所以你要下订单然后让人家做饭给你吃对吧,你就是CPU你有需求想要渲染一个物体或者一个纹理但是你没有渲染能力所以你要给GPU下订单让GPU来渲染,餐馆就好比GPU。

你给餐馆下订单的过程就是一次DrawCall,假设你点了一盘鱼香肉丝,而另外一个人也来吃饭他点了一盘宫保鸡丁,这样你俩分别下单后,餐馆后厨就要先做一盘鱼香肉丝然后再做一盘宫保鸡丁。但是假如你和他都想吃鱼香肉丝,那么你俩可以选择拼一个单(合并批处理)然后餐馆后厨只需要一次性炒出2人份的鱼香肉丝就可以了,是不是第二种更快一些?

所以能合并处理的就合并处理(CPU把原本需要多次分批提交的渲染请求合并成一次提交给GPU,吃饭的两个人拼个单)这样有助于提高效率,但是你会发现并不是所有情况下都可以合并处理,比如如果渲染的内容不一样(你吃鱼香肉丝他吃宫保鸡丁),那就没办法合并,所以优化也是有前提条件的满足一定条件的才能优化合并处理。

Mantra
3楼 · 2020-04-20 10:28

1)在unity中,每次CPU准备数据并通知GPU的过程就称之为一个DrawCall。具体过程就是:设置颜色-->绘图方式-->顶点坐标-->绘制-->结束,所以在绘制过程中,如果能在一次DrawCall完成所有绘制就会大大提高运行效率,进而达到优化的目的。

2)优化DrawCall可以从以下几个方面:

设置图集、共用材质、激活批处理、减少实时光的使用及阴影。


男孩无衣
4楼 · 2020-04-20 10:39

Unity每次在准备数据并通知GPU渲染的过程称为一次DrawCall。


说白了,就是CPU计算游戏对象的位置、使用的图片、运动状态等信息, 然后把这些信息通过BUS总线,传送给GPU绘制出来的一次完整流程,就是一次DrawCall。


DrawCall直接影响渲染的速度,渲染速度又与Update执行频率有关,所以通常来讲,降低DrawCall有两个方面。CPU和GPU方面。


一、从CPU角度


①静态和动态批处理:批处理相同材质静态对象或相同纹理的静态对象

静态批处理:将使用相同材质的对象,合并成一次DrawCall进行渲染。

image.png

动态批处理:Unity自动分析场景中哪些对象可以合并。我们并不能深刻干预,所以还是优先使用静态批处理。

image.png

②从物理组件角度优化:设置一个合适的Fixed Timestep、不要使用MeshCollider、网格合并 (MeshBaker)

从优化的角度来看,尽量少的使用物理组件,能通过数学计算的尽量计算,物理引擎相对来讲会更耗费性能。


③较少内存中垃圾数据的产生,减少CPU在GC方面的消耗。手段如下:

⭐️字符串连接的处理。因为将两个字符串连接的过程,其实是生成一个新的字符串的过程。而之前的旧的字符串自然而然就成为了垃圾。而作为引用类型的字符串,其空间是在堆上分配的,被弃置的旧的字符串的空间会被GC当做垃圾回收。

⭐️尽量不要使用foreach,而是使用for。foreach其实会涉及到迭代器的使用,而据传说每一次循环所产生的迭代器会带来24 Bytes的垃圾。那么循环10次就是240Bytes。

⭐️不要直接访问gameobject的tag属性。比如if (go.tag == “human”)最好换成if (go.CompareTag (“human”))。因为访问物体的tag属性会在堆上额外的分配空间。如果在循环中这么处理,留下的垃圾就可想而知了。

⭐️使用“池”,以实现空间的重复利用。对象池

⭐️最好不用LINQ 的命令,因为它们会分配临时的空间,同样也是GC收集的目标。在某些情况下LINQ无法很好的进行AOT编译。比如“OrderBy”会生成内部的泛型类“OrderedEnumerable”。这在AOT编译时是无法进行的,因为它只是在OrderBy的方法中才使用。所以如果你使用了OrderBy,那么在IOS平台上也许会报错。


④通过代码质量减少CPU压力:

⭐️不要频繁使用GetComponent\Find\,尤其是在循环中

⭐️善于使用OnBecameVisible()和OnBecameInvisible()

⭐️使用内建的数组,比如用Vector3.zero而不是new Vector(0, 0, 0)

⭐️善于使用ref关键字. 传参(值), 值拷贝, 取值类型的地址

⭐️将经常需要使用的属性查询缓存起来

⭐️不要频繁使用Instantiate和Destroy(GameObject)设置为非激活

以上为CPU方面的优化策略。


二、GPU方面降低DrawCall


①减少画面中需要绘制的数目

⭐️保持材质的数目尽可能少。这使得Unity更容易进行批处理。

⭐️使用纹理图集(一张大贴图里包含了很多子贴图)来代替一系列单独的小贴图。它们可以更快地被加载,具有很少的状态转换,而且批处理更友好。

⭐️如果使用了纹理图集和共享材质,使用Renderer.sharedMaterial 来代替Renderer.material 。

⭐️使用光照纹理(lightmap)而非实时灯光。

⭐️遮挡剔除(Occlusion culling)

⭐️使用LOD(多层次细节),好处就是对那些离得远,看不清的物体的细节可以忽略。

⭐️使用mobile版的shader,简单。


②使用MipMaps优化显存带宽

image.png

image.png

它的原理是当屏幕变小时,自动选择合适尺寸的图片进行渲染;但会多使用33%的内存。


三、从内存方面优化,主要使用对象池技术。有关对象池的实现,可自行百度,有大量、各式各样的实现方法。



Ross
5楼 · 2020-04-20 20:22

在游戏运行时,CPU每通知一次GPU渲染一次的过程,称为一次DrawCall,可以肯定的是DrawCall的值越大,GPU渲染的次数就越多,游戏运行的性能就越低,故在后期项目优化的时候会尽量的减少DrawCall的值,一般的做法有以下几点:图片尽量使用精灵打包,减少模型网格的顶点数,减少光照和实时渲染,尽量使用光照贴图,使用静动态批处理,LOD等。

小狮子
6楼 · 2020-04-20 22:09

DrawCall的含义就是CPU调用图像编程接口,以命令GPU进行渲染的操作。

优化有一下几个解决方案:

        1、使用Draw Call Batching,也就是批处理。Unity在运行时可以将一些物体进行合并,从而用一个DrawCall来渲染他们。

        2、通过把纹理打包成图集来尽量减少材质的使用。

        3、尽量少的使用反光,阴影之类的,因为那会使物体多次渲染。


蜗牛
7楼 · 2020-05-10 09:26

CPU每通知一次GPU渲染一次的过程,称为一次DrawCall

减少DrawCall,可以使用打包图集,减少模型顶点数,减少光照,使用光照贴图,LOD等技术都可以降低DrawCall

征戰撩四汸
8楼 · 2021-11-09 15:33

   

     DrawCall的含义就是CPU调用图像编程接口,以命令GPU进行渲染的操作。

    CPU和GPU通过使用一个命令缓冲区实现并行工作。命令缓冲区包含一个命令队列,CPU向其中添加命令,GPU从中读取命令,添加和读取是相互独立的,因此使得CPU和GPU可以独立工作。命令缓冲区中的命令有很多种类,DrawCall就是其中一种。

    减少方法:

    1、使用Draw Call Batching,也就是批处理。Unity在运行时可以将一些物体进行合并,从而用一个DrawCall来渲染他们。具体下面会介绍。

    2、通过把纹理打包成图集来尽量减少材质的使用。

    3、尽量少的使用反光,阴影之类的,因为那会使物体多次渲染。


相关问题推荐

  • 回答 5

    第一种方法:通过点击场景文件打开Unity游戏工程找到Unity游戏工程所在的目录,我这里的工程放在在E盘根路径的Unity_workspace文件夹中。注意:unity软件不支持中文路径,所以不要把工程放在中文文件夹下。我们在这里就打开New Unity Project 4工程,进入到Ne...

  • 回答 13
    已采纳

    如果是学习研究的话,当然是体验官方的最新版本。要是项目开发的话,还是要选择长期稳定版本,也就是大版本的LTS。比如2017.4或者是2018.4都是LTS版本,至于后面的小版本可以去看下更新的内容来做选择吧!...

  • 回答 9

    unity3D是实时3D互动内容创作和运营平台。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助Unity将创意变成现实。Unity平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC...

  • 回答 11

    1、Unity3D:如果你需要开发大型游戏,或需要开发3D游戏的,请选这个。2、Cocos2D-x:如果你开发的是中小型游戏,对安装包大小比较在意的,请选这个。3、Andengine、Cocos2D-iPhone:如果你只为开发单平台游戏,又非常在意速度和安装包大小,请选这个。最后。...

  • 回答 11

    首先在场景中调整好你要观看的视角选择摄像机,按下Ctrl+Shift+F或者菜单栏->GameObject->Align with view在不行的话,可以调整摄像机的Position 和 Rotation

  • 回答 5

    将MeshRender组件移除即可:

  • 回答 9

    1.在Asset store里选择一个skybox。 2.从素材库中选择一个人物角色,也可以自己建模或者在其他软件中做好再导进来。 3.想好角色如何运动,然后用自己比较熟悉的语言编写来作展示,这段代码可以实现当你按下键盘上的A/D/S/W的按键时,角色会向前后左右四个方向的...

  • 回答 17

    还是要学好编程基础呀如果你觉得编程很苦难 不一定要从c#开始学  学学js flash as等等  有个梯度就好多了如果要用好unity  不会编程那是不行的  学习的过程中都有个头疼的过程  记住  头越痛  代表你要接受的东西越多  坚持 你的大脑在和知识兼容中:D...

  • 回答 4

    xcel 表的操作少不了要引入第三方库,首先我们需要引入 Excel.dll 和 ICSharpCode.SharpZipLib.dll,这两个类库在网上都能找到;然后我们还需要引入 System.Data.dll,这个类库在 Unity3D 的安装路径下的 Editor\Data\Mono\lib\mono\unity 文件夹下能找到...

  • 回答 1

    需要添加如下引用: System.Configuration System.Data System.EnterpriseServices System.Security System.XML using UnityEngine; using System.Collections; using System;  using  System.Data;  using System.Data...

  • 物理引擎问题2021-06-15 17:35
    回答 4

    物理引擎则使用动量、扭矩等用高等数学手段来模拟真实物体,这将得到更真实的效果且使我们的编码更加容易。

  • 回答 1

    不能这样表述,三维通常是立体的空间,二维则是平面的。数学中通常是Oxyz表示空间直角坐标系,Oxy表示表示的是平面直角坐标系,你可以说空间直角坐标系中去掉Z轴可以转换为二维,因为去掉X或Y轴都能转换为二维。...

  • 回答 2

    GameObject.renderer.enabled//是控制一个物体是否在屏幕上渲染或显示 而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的GameObject.Destroy()//表示移除物体或物体上的组件 代表销毁该物体 实际上该物体的内存并没有立即释放,而是等到这...

  • Canvas三种渲染模式2021-04-29 19:50
    回答 10

    一:Overlay—覆盖模式类似于手机贴膜,所有UI都会显示在场景中2D,3D物体的上层在同一个Canvas下可以调整Canvas子物体的先后顺序,层级面板中越靠上则先被渲染多个Canvas下可以调整Canvas组件的Sort Order属性调整渲染顺序,数值越小的画布越先被渲染:Camer...

  • Unity引擎2021-04-29 19:47
    回答 4

    不得不说,Unity3d是个解放生产力的游戏引擎,自带了各种编辑器,可以进行一系列的可视化操作。需要注意的是,unity3d适合FPS游戏,物理游戏等中小型的游戏,并不太适合MMO开发。unity3d难学吗?如何学习unity3d呢?在学习之前又应该了解哪些内容呢?代码写不...

  • 回答 3

    不是人工检查的,如果你的问题里面有敏感关键字,是发不出去的,现在国内所有的网站在发布文章时都要进行检查的,所以你在发之前先检查一下看问题里面是否有违禁词语。

没有解决我的问题,去提问