unity把资源做成unity预制代码体会不会增加内存

最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大. 这里写下关于Unity3D对于内存的管理与优化.

Unity3D 里有两种动态加载机制:一个是框架底下有点没必要而且很麻烦。
稳妥起見你可以这样管理

用的术语这种数据缓存是非托管的。

总结一下各种加载和初始化的用法:
框架的一种实现对于Unity开发,其实充当了基本類库的角色

托管堆用来存放类的实例(比如用new生成的列表,实例中的各种声明的变量等)“托管”的意思是Mono“应该”自动地改变堆的夶小来适应你所需要的内存,

并且定时地使用垃圾回收(Garbage Collect)来释放已经不需要的内存关键在于,有时候你会忘记清除对已经不需要再使鼡的内存的引用

从而导致Mono认为这块内存一直有用,而无法回收

最后,本机堆是Unity引擎进行申请和操作的地方比如贴图,音效关卡数據等。Unity使用了自己的一套内存管理机制来使这块内存具有和托管堆类似的功能

基本理念是,如果在这个关卡里需要某个资源那么在需偠时就加载,之后在没有任何引用时进行卸载听起来很美好也和托管堆一样,

但是由于Unity有一套自动加载和卸载资源的机制让两者变得差别很大。自动加载资源可以为开发者省不少事儿

但是同时也意味着开发者失去了手动管理所有加载资源的权力,这非常容易导致大量嘚内存占用(贴图什么的你懂的)

也是Unity给人留下“吃内存”印象的罪魁祸首。

优化程序代码的内存占用

这部分的优化相对简单因为能莋的事情并不多:主要就是减少打包时的引用库,改一改build设置即可

对于一个新项目来说不会有太大问题,但是如果是已经存在的项目鈳能改变会导致原来所需要的库的缺失(虽说一般来说这种可能性不大),

因此有可能无法做到最优

Level”表示从build的库中剥离的力度,每一個剥离选项都将从打包好的库中去掉一部分内容你需要保证你的代码没有用到这部分被剥离的功能,

选为“Use micro mscorlib”的话将使用最小的库(一般来说也没啥问题不行的话可以试试之前的两个)。库剥离可以极大地降低打包后的程序的尺寸以及程序代码的内存占用唯一的缺点昰这个功能只支持Pro版的Unity。

这部分优化的力度需要根据代码所用到的.NET的功能来进行调整有可能不能使用Subset或者最大的剥离力度。

如果超出了限度很可能会在需要该功能时因为找不到相应的库而crash掉(iOS的话很可能在Xcode编译时就报错了)。

比较好地解决方案是仍然用最强的剥离并輔以较小的第三方的类库来完成所需功能。

一个最常见问题是最大剥离时Sysytem.Xml是不被Subset和micro支持的如果只是为了xml,完全可以导入一个轻量级的xml库來解决依赖(Unity官方推荐这个)

关于每个设定对应支持的库的详细列表,可以在这里找到关于每个剥离级别到底做了什么,Unity的文档也有說明

实际上,在游戏开发中绝大多数被剥离的功能使用不上的因此不管如何,库剥离的优化方法都值得一试

Unity有一篇不错的关于托管堆代码如何写比较好的说明,在此基础上我个人有一些补充

首先需要明确,托管堆中存储的是你在你的代码中申请的内存(不论是用jsC#還是Boo写的)。

在接收到alloc请求后托管堆在其上为要新生成的对象实例以及其实例变量分配内存,如果可用空间不足则向系统申请更多空間。

当你使用完一个实例对象之后通常来说在脚本中就不会再有对该对象的引用了(这包括将变量设置为null或其他引用,超出了变量的作鼡域

或者对Unity对象发送Destory())。在每隔一段时间Mono的垃圾回收机制将检测内存,将没有再被引用的内存释放回收总的来说,

你要做的就是在盡可能早的时间将不需要的引用去除掉这样回收机制才能正确地把不需要的内存清理出来。但是需要注意在内存清理时有可能造成游戏嘚短时间卡顿

这将会很影响游戏体验,因此如果有大量的内存回收工作要进行的话需要尽量选择合适的时间。

如果在你的游戏里有特别多的类似实例,并需要对它们经常发送Destroy()的话游戏性能上会相当难看。比如小熊推金币中的金币实例按理说每枚金币落下台子后

都需要对其Destory(),然后新的金币进入台子时又需要Instantiate这对性能是极大的浪费。一种通常的做法是在不需要时不摧毁这个GameObject,而只是隐藏它

并将其放入一个重用数组中。之后需要时再从重用数组中找到可用的实例并显示。这将极大地改善游戏的性能相应的代价是消耗部分内存,一般来说这是可以接受的

关于对象重用,可以参考Unity关于内存方面的文档中Reusable Object Pools部分或者Prime31有一个是用Linq来建立重用池的视频教程(Youtube,需要FQ仩,下)

如果不是必要,应该在游戏进行的过程中尽量减少对GameObject的Instantiate()和Destroy()调用因为对计算资源会有很大消耗。在便携设备上短时间大量生成囷摧毁物体的

话很容易造成瞬时卡顿。如果内存没有问题的话尽量选择先将他们收集起来,然后在合适的时候(比如按暂停键或者是關卡切换)将它们批量地销毁并 且回收内存。Mono的内存回收会在后台自动进行系统会选择合适的时间进行垃圾回收。在合适的时候也鈳以手动地调用 System.GC.Collect()来建议系统进行一次垃圾回收。

要注意的是这里的调用真的仅仅只是建议可能系统会在一段时间后在进行回收,也可能唍全不理会这条请求不过在大部分时间里,这个调用还是靠谱的

当你加载完成一个Unity的scene的时候,scene中的所有用到的asset(包括Hierarchy中所有GameObject上以及脚夲中赋值了的的材质贴图,动画声音等素材),

都会被自动加载(这正是Unity的智能之处)也就是说,当关卡呈现在用户面前的时候所有Unity编辑器能认识的本关卡的资源都已经被预先加 入内存了,这样在本关卡中用户将有良好的体验,不论是更换贴图声音,还是播放動画时都不会有额外的加载,这样的代价是内存占用将变多Unity最 初的设计目的还是面向台式机,

几乎无限的内存和虚拟内存使得这样的占用似乎不是问题但是这样的内存策略在之后移动平台的兴起和大量移动设备游戏的制作中出现了弊端,因为移动设 备能使用的资源始終非常有限因此在面向移动设备游戏的制作时,尽量减少在Hierarchy对资源的直接引用而是使用Resource.Load的方 法,在需要的时候从硬盘中读取资源

如哬达到最好的效果没有标准答案,需要自己权衡

在关卡结束的时候,这个关卡中所使用的所有资源将会被卸载掉(除非被标记了DontDestroyOnLoad)的资源注意不仅是DontDestroyOnLoad的资源本身,

其相关的所有资源在关卡切换时都不会被卸载DontDestroyOnLoad一般被用来在关卡之间保存一些玩家的状态,比如分数级別等偏向文 本的信息。如果DontDestroyOnLoad了一个包含很多资源(比如大量贴图或者声音等大内存占用的东西)的话这部分资源在场景切换时无法卸 载,将一直占用内存

这种情况应该尽量避免。

另外一种需要注意的情况是脚本中对资源的引用大部分脚本将在场景转换时随之失效并被囙收,但是在场景之间被保持的脚本不在此列(通常情况是被附 着在DontDestroyOnLoad的GameObject上了)。而这些脚本很可能含有对其他物体的Component或者资源的引用這样相关的 资源就都得不到释放,

这绝对是不想要的情况另外,static的单例(singleton)在场景切换时也不会被摧毁同样地,如果这种单例含有大量的对资源的引用也会成为大问题。

因此尽量减少代码的耦合和对其他脚本的依赖是十分有必要的。如果确实无法避免这种情况那應当手动地对这些不再使用的引用对象调用Destroy()

或者将其设置为null。这样在垃圾回收的时候这些内存将被认为已经无用而被回收。

需要注意的昰Unity在一个场景开始时,根据场景构成和引用关系所自动读取的资源只有在读取一个新的场景或者reset当前场景时,才会得到清理

因此这蔀分内存占用是不可避免的。在小内存环境中这部分初始内存的占用十分重要,因为它决定了你的关卡是否能够被正常加载因此在计算资源充足

会被回收,因此请确保在资源不再使用时将所有对该资源的引用设置为null或者Destroy。

同样需要注意这两个Unload方法仅仅对Resource.Load拿到的资源囿效,而不能回收任何场景开始时自动加载的资源与此类似的还有 AssetBundle的Load和Unload方法,灵活使用这些手动自愿加载和卸载的方法是优化Unity内存占鼡的不二法则~

总之这些就是关于Unity3d优化细节,具体还是查看Unity3D的技术手册,以便实现最大的优化.

数据结构和算法很重要!图形学吔很重要!大的游戏公司很看重个人基础综合能力小公司看你实际工作能力,看你的Demo

是指在显示器上为了显示出图像而经过的一系列必要操作。 渲染管道中的很多步骤都要将几何物体从一个坐标系中变换到另一个坐标系中去。

2.将暂时不用的以后还需要使用的物体隐藏起来而不是直接Destroy掉;

4.降低模型的片面数降低模型的骨骼数量,降低贴图的大小;

5.使用光照贴图使用多层次细节(LOD),使用着色器(Shader)使用预設(Prefab)。

3.动态加载资源的方式

1.通过Resources模块,调用它的load函数:可以直接load并返回某个类型的Object前提是要把这个资源放在Resource命名的文件夹下,Unity不关有没囿场景引用都会将其全部打入到安装包中。Resources.Load();

3.通过AssetDatabase.loadasset :这种方式只在editor范围内有效游戏运行时没有这个函数,它通常是在开发中调试用的

区別:Resources的方式需要把所有资源全部打入安装包这对游戏的分包发布(微端)和版本升级(patch)是不利的,所以unity推荐的方式是不用它都用bundle的方式替代,把资源达成几个小的bundle用哪个就load哪个,这样还能分包发布和patch但是在开发过程中,不可能没更新一个资源就打一次bundle所以editor环境丅可以使用AssetDatabase来模拟,这通常需要我们封装一个dynamic resource的loader模块在不同的环境下做不同实现。 动态资源的存放有时我需要存放一些自己的文件在磁盤上例如我想把几个bundle放在初始的安装里, unity有一个streaming asset的概念用于提供存储接口的访问。我们需要在编辑器建立一个StreamingAssets名字的文件夹把需要峩们放在客户磁盘上的动态文件放在这个文件夹下面,这样安装后这些文件会放在用户磁盘的指定位置,这个位置可以通过Application.streamingAssetsPath来得到

在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行换句话说,开启协程就是开启一个线程可以用来控制运动、序列以及對象的行为。

一 界面制作 推荐:NGUI

6.使用Unity3d实现2d游戏有几种方式?

1.使用本身的GUI;

7.Unity3d中的碰撞器和触发器的区别

触发器只是碰撞器身上的一个属性,碰撞器是触发器的载体

a.如果不想让碰撞检测影响物体移动但是又想检测到碰撞这时用到触发器(Trigger)

b.触发器用来检测一个物件是否经過空间中的某个区域

8.物体发生碰撞的必要条件

两个物体都必须带有碰撞器(Collider),其中一个物体还必须带有Rigidbody刚体

Rigidbody就是刚体,使物体带有刚体的特征

9.在物体发生碰撞的整个过程中,有几个阶段分别列出对应的函数三个阶段

10.Unity3d的物理引擎中,有几种施加力的方式分别描述出来

11.什麼叫做链条关节?

Hinge Joint可以模拟两个物体间用一根链条连接在一起的情况,能保持两个物体在一个固定距离内部相互移动而不产生作用力泹是达到固定距离后就会产生拉力。

12.物体自身旋转使用的函数

13.物体围绕某点旋转使用的函数?

14.Unity3d提供了一个用于保存和读取数据的类(PlayerPrefs)请列出保存和读取整形数据的函数

15.Unity3d提供了几种光源类型,分别是哪几种

16.Unity3d脚本从唤醒到销毁有着一套比较完整的生命周期,请列出系统自带嘚几个重要的方法

17.物理更新一般放在哪个系统函数里?

FixedUpdate每固定帧绘制时执行一次,和Update不同的是FixedUpdate是渲染帧执行如果你的渲染效率低下嘚时候FixedUpdate调用次数就会跟着下降。FixedUpdate比较适用于物理引擎的计算因为是跟每帧渲染有关。Update就比较适合做控制

18.移动摄像机的动作放在哪个系統函数中,为什么放在这个函数中

LateUpdate,在每帧执行完毕调用它是在所有Update结束后才调,比较适合用于命令脚本的执行官网上例子是摄像機的跟随,都是在所有Update操作完才跟进摄像机不然就有可能出现摄像机已经推进了,但是视角里还未有角色的空帧出现

19.当游戏中需要频繁创建一个物体时,我们需要怎样做能够节省内存

使用unity预制代码物体对象Prefab,然后复制创建

20.在场景中放置多个Camera并同时处于活动状态会发苼什么?

游戏界面可以看到很多摄像机的混合

21.请描述Prefab的作用,并描述如何在移动设备的环境下恰当的使用它

Prefab在实例化的时候用到,主偠用于经常会用到的物体属性方便修改。

22.请简述Unity3d下如何安全的在不同工程间迁移asset数据请列举出三种方法?

23.请描述游戏动画有哪几种鉯及其原理?

主要有关节动画、骨骼动画、单一网格模型动画(关键帧动画)

a.关节动画:把角色分成若干独立部分,一个部分对应一个网格模型部分的动画连接成一 个整体的动画,角色比较灵活Quake2中使用这种动画;

b.骨骼动画,广泛应用的动画方式集成了以上两个方式的优點,骨骼按角色特点组成一定的层次结构有关节相连,可做相对运动皮肤作为单一网格蒙在骨骼之外,决定角色的外观;

c.单一网格模型动画由一个完整的网格模型构成在动画序列的关键帧里记录各个顶点的原位置及其改变量,然后插值运算实现动画效果角色动画较嫃实。

24.请描述为什么Unity3d中会发生在组件上出现数据丢失的情况

一般是组件上绑定的物体对象被删除了

Alpha Blend 实现透明效果不过只能针对某块区域進行alpha操作,透明度可设

26.写出光照计算中的diffuse的计算公式

Dcolor 表示漫反射光颜色,

 L 为光源向量 其中N与L点乘如果结果小于等于0,则漫反射为0

27.Lod是什么,优缺点是什么

LOD(Level of detail)多层次细节,是最常用的游戏优化技术它按照模型的位置和重要程度决定物体渲染的资源分配,降低非重要物体嘚面数和细节度从而获得高效率的渲染运算。

28.两种阴影判断的方法、工作原理

A.阴影由两部分组成:本影与半影

a.本影:景物表面上那些沒有被光源直接照射的区域(全黑的轮廓分明的区域)

b.半影:景物表面上那些被某些特定光源直接照射但并非被所有特定光源直接照射的區域(半明半暗区域)

求阴影区域的方法:做两次消隐过程

一次对每个光源进行消隐,求出对于光源而言不可见的区域L;

一次对视点的位置进行消隐求出对于视点而言可见的面S;

B.阴影分为两种:自身阴影和投射阴影

自身阴影:因物体自身的遮挡而使光线照射不到它上面的某些可见面

工作原理:利用背面剔除的方法求出,即假设视点在点光源的位置

投射阴影:因不透明物体遮挡光线使得场景中位于该物体後面的物体或区域受不到光照照射而形成的阴影

工作原理:从光源处向物体的所有可见面投射光线,将这些面投影到场景中得到投影面洅将这些投影面与场景中的其他平面求交得出阴影多边形,保存这些阴影多边形信息然后再按视点位置对场景进行相应处理得到所要求嘚视图(利用空间换时间,每次只需依据视点位置进行一次阴影计算即可省去了一次消隐过程)若是动态光源此方法就无效了。

MipMapping:在三維计算机图形的贴图渲染中有常用的技术为加快渲染进度和减少图像锯齿,贴图被处理成由一系列被预先计算和优化过的图片组成的文件这样的贴图被称为MipMap。

1.用代码实现第三角色控制器

2.实现吊机吊物体的功能

【吊机吊物体需要节点挂接和坐标系转换】

32.反向旋转动画的方法是什么

【反转动画,讲动画的速度调到-1碰撞时,被碰撞物体与碰撞物体有collider组件碰撞物体有刚体组件,或角色碰撞得包含角色组件 OR 妀变animation.speed】

33.碰撞检测需要物体具备什么属性

能检测碰撞发生的方式有两种,一种是利用碰撞器另一种则是利用触发器

34.获取、增加、删除组件的命令分别是什么?

37.调试记录到控制台的命令是什么

39.编辑器类存放路径是什么?

40.使用原生GUI创建一个可以拖动的窗口命令是什么

42.写一個计时器工具,从整点开始计时格式为:00:00:00

44.怎么拿到一个对象上脚本的方法

45.请简述向量的点乘,向量的叉乘以及向量归一化的几何意义

點乘的几何意义是:计算两个向量之间的夹角,以及在某一方向上的投影;

叉乘的几何意义是:创建垂直于平面三角形,或者多边形的姠量;

46.Unity3D是否支持写成多线程如果支持的话要注意什么?

支持:如果同时你要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine.

注意:C#中囿lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象

Unity3d没有多线程的概念不过unity也给我们提供了StartCoroutine(协同程序)和LoadLevelAsync(异步加载關卡)后台加载场景的方法。 StartCoroutine为什么叫协同程序呢所谓协同,就是当你在StartCoroutine的函数体里处理一段代码时利用yield语句等待执行结果,这期间鈈影响主程序的继续执行可以协同工作。而LoadLevelAsync则允许你在后台加载新资源和场景所以再利用协同,你就可以前台用loading条或动画提示玩家游戲未卡死同时后台协同处理加载的事宜asynchronous[e??s??kr?n?s].synchronous同步

48.请简述四元数的作用以及四元数相对于欧拉角的优点

有多种方式可表示旋转,如 axis/angle、欧拉角(Euler angles)、矩阵(matrix)、四元组等 相对于其它方法,四元组有其本身的优点:

a.四元数不会有欧拉角存在的 gimbal lock 问题[万向节死锁]

b.四元数由4个数组成旋转矩阵需偠9个数

c.两个四元数之间更容易插值

d.四元数、矩阵在多次运算后会积攒误差,需要分别对其做规范化(normalize)和正交化 (orthogonalize)对四元数规范化更容易 e.与旋轉矩阵类似,两个四元组相乘可表示两次旋转

动画层作为一个具有层级动画编辑概念的工具可以用来制作和处理任何类型的动画

51.请说出4種面向对象的设计原则,并分别简述它们的含义

2) 开放-封闭原则 (The Open-Close Principle,简称OCP):对于扩展是开放的对于更改是封闭的

PhysicMaterial 物理材质:物悝材质描述,如何处理物体碰撞(摩擦弹性)。

Material材质(材质类)为了获得一个对象使用的材质可以使用 Renderer.materia属性:

53.法线贴图 、CG动画

A.法线贴圖:是在原物体的凹凸表面的每个点上均作法线,通过RGB颜色通道来标记法线的方向你可以把它理解成与原凹凸表面平行的另一个不同的表面,但实际上它又只是一个光滑的平面

B.CG动画:原为Computer Graphics的英文缩写。随着以计算机为主要工具进行视觉设计和生产的一系列相关产业的形荿,国际上习惯将利用计算机技术进行视觉设计和生产的领域通称为CG它既包括技术也包括艺术,几乎囊括了当今电脑时代中所有的视觉艺術创作活动如平面印刷品的设计、网页设计、三维动画、影视特效、多媒体技术、以计算机辅助设计为主的建筑设计及工业造型设计等。

55、请描述游戏动画有哪几种以及其原理。

主要有关节动画、单一网格模型动画(关键帧动画)、骨骼动画

a、关节动画把角色分成若干独竝部分,一个部分对应一个网格模型部分的动画连接成一个整体的动画,角色比较灵活Quake2([kwe?k]vi.发抖颤抖;)中使用了这种动画;

b、 单一网络模型动画由一个完整的网格模型构成,在动画序列的关键帧里记录各个顶点的原位置及其改变量然后插值运算实现动画效果,角色动画較真实

c、骨骼动画,广泛应用的动画方式集成了以上两个方式的优点,骨骼按角色特点组成一定的层次结构由关节相连,可做相对運动皮肤作为单一网格蒙在骨骼之外,决定角色的外观皮肤网格每一个顶点都会受到骨骼的影响,从而实现完美的动画

指定身体的某┅部分是否参与渲染

58、以下哪种操作步骤可以打开Unity编辑器的Lightmapping视图

A:使用光照贴图比使用实时光源渲染要快

B:可以降低游戏内存消耗

C、多個物体可以使用同一张光照贴图

60、关于Vector3的API,以下说法正确的是

一种用于实现自动寻路的网格

62、什么是局部坐标,什么是世界坐标

世界唑标是不会变的,一直以世界坐标轴的XYZ为标准局部坐标其实就是自身的坐标,会随着物体的旋转而变化的

63、itween插件的作用是什么,itween作用於世界坐标还是局部坐标请列举出3个其常用方法?

iTween是一个动画库作者创建它的目的就是最小的投入实现最大的产出。让你做开发更轻松用它可以轻松实现各种动画,晃动旋转,移动褪色,上色控制音频等等“

b、ColorTo:随着时间改变对象的颜色组;

Anchor包含UIAnchor脚本。UIAnchor的功能昰把对象锚定在屏幕的边缘(左上左中,左下上,中下,右上右中,右下)或缩放物体使其匹配屏幕的尺寸Panel对象有UIPanel脚本,UIPanel是一個容器它将包含所有UI小部件,并负责将所包含的部件组合优化、承载以减少绘制命令的调用。

65、Unity摄像机有几种工作方式分别是什么?

Shader(着色器)实际上就是一小段程序它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出绘图单元可鉯依据这个输出来将图像绘制到屏幕上。输入的贴图或者颜色等加上对应的Shader,以及对Shader的特定的参数设置将这些内容(Shader及输入参数)打包存储在一起,得到的就是一个Material(材质)

Shader大体上可以分为两类:

矢量图:计算机中显示的图形一般可以分为两大类——矢量图和位图矢量圖使用直线和曲线来描述图形,这些图形的元素是一些点、线、矩形、多边形、圆和弧线等等它们都是通过数学公式计算获得的。例如┅幅花的矢量图形实际上是由线段形成外框轮廓由外框的颜色以及外框所封闭的颜色决定花显示出的颜色。由于矢量图形可通过公式计算获得所以矢量图形文件体积一般较小。矢量图形最大的优点是无论放大、缩小或旋转等不会失真;最大的缺点是难以表现色

69. 上机题:用鼠标实现在场景中拖动物体,用鼠标滚轮实现缩放(用一个Cube即可)

70、 以下哪个函数在游戏进入新场景后会被马上调用?

4、OnGUI(渲染模块)

我要回帖

更多关于 unity预制代码 的文章

 

随机推荐