【Unity高频面试题】借助这些积累收获大厂offer
计算机专业的小伙伴们在找工作的时候,常常提到八股。那么什么是八股呢?下面博主就和大家说一说自己的看法~
作为一名软件工程专业在校生,八股就是在笔试或者面试过程中经常遇到的知识点,通用的有 网络原理、网络编程、操作系统、计算机组成原理、数据库 这些,特定的就是岗位强相关的技术和面对对象语言。
对于互联网前后端而言,Java 一般是强相关的语言(在此基础上,字节青睐 Golong,腾讯青睐C++);对于游戏研发来说,C++ / C# / Lua 就是强相关的语言,强相关的技术一般有 Unity / Unreal / Cocos / 计算机图形学 / OpenGL...;对于测试开发来说,测试开发相关的 自动化测试 / 黑盒测试 / 白盒测试 以及一些测试开发工具(比如 Jmeter / Postman / Selenium)就是强相关的。
对于经验不足的校招生或者找实习的同学来说,可能并不是那么容易的就能获取面试相关的一些资源。
小虾在这次的春季招聘中,经历了包括(腾讯天美、腾讯魔方、网易雷火、阿里巴巴灵犀互娱、吉比特雷霆、完美世界、三七互娱、字节跳动朝夕光年、剑心互娱、飞鱼科技)等名厂的面试,也收获到了心仪项目组的offer和不错的薪资待遇。
下面就和大家分享分享我所遇到的重点八股!首次分享的是Unity篇【不过还是建议大家去B站进行一个深入的学习,只有对知识有足够深入、深刻以及不失广度的理解,才能在面试中更加从容】
Unity八股
为了方便记忆,简化处理了不少说法,对大家可能有点拗口,见谅
U3d完整的生命周期
Awake——>Start——>Update——>FixedUpdate——>LateUpdate——>OnGUI——>Reset——>OnDisable——>OnDestroy
OnEnable/Awake/Start发生顺序?哪些可能在同一个对象周期中反复发生
Awake–>OnEnable->Start,OnEnable在同一周期中可以反复地发生!
对象池简述,FPS里哪些东西适合使用对象池
对象池就存放需要被反复调用资源的一个空间,比如游戏中要常被大量复制的对象,子弹,敌人,以及任何重复出现的对象。
逐顶点/像素着色的区别
先计算再插值/先插值后计算。控制粒度是三角形/像素【逐顶点和逐片元:逐顶点速度快,但颜色不平滑,会出现锯齿】
人物静止到跑动到攻击,状态机是如何实现的
animator controller的运转相关,设置三个状态动画与转移条件,代码判断状态机转移
Animator和Animation
主要用于tween/属性 动画,后者能能更精确得控制动画
热更新
不停机实时更新,真正的热更新是不用重启,Android不能达到完全的真正热更新。热更新出现之前,通过反射注解/反射调用/反射注入等方式已经可以实现类的动态加载了。热更新的实质就是替换,需要替换运行时新的类和资源文件的加载,可认为是热操作。是种改变app运行行为的技术,本质是利用hook操作进行替换,代码上是种侵入性操作。
点乘和叉乘
点乘(内积/数量积),运算法则:a·b=|a||b|cos。几何意义:表示/计算两个向量之间的夹角,以及在b向量在a向量方向上的投影。点乘结果越大表示余弦值越大,夹角越小,两向量越接近。
叉乘(外积/向量积),运算法则:a·b=|a||b|sin。几何意义:三维几何中,向量a和b的叉乘是法向量,法向量垂直于a和b向量构成的平面;因此3D图像学中,可以通过两个向量的叉乘,生成第三个垂直于a,b的法向量,从而构建X、Y、Z坐标系。
判断这点是否在一个倾斜圆柱内
叉乘:圆柱轴线两端点能直接取到,跟判定点形成三角形,求三角形的垂线的模
点乘:先取到垂线向量,然后|AP - AB * AP / |AB||,判断是不是在圆柱里面
程序闪退与卡顿原因
闪退4大原因:1.内存泄漏/加载资源时闪退 2.CPU角度,执行过于复杂的运算 3.系统内存回收机制,按照优先级回收内存。内存资源紧张时会回收前台进程,可能杀掉进程 4.兼容性问题,程序对目标设备的软硬件兼容不好
卡顿:某帧堆积的任务过多——采用多线程 或 把任务平摊到多个帧执行
欧拉角/四元数/旋转矩阵
这俩比起矩阵,更节省存储空间和方便插值。四元数用来表示旋转,相对于欧拉角,能增量旋转,避免万象锁(欧拉角因旋转顺序造成问题),给定方位的表达式有两种,即互为负
四元数Quaternion的作用&相对欧拉角的优点
四元数用于表示旋转,相对欧拉角的优点:能进行增量旋转、避免万向锁、给定方位的表达方式有两种,互为负(欧拉角有无数种表达方式)
U3d渲染过程/(GPU)渲染流水线
U3D Shader分哪几种,有什么区别
1)表面着色器:象层次比较高,轻松简洁方式实现复杂着色。表面着色器可在前向渲染&延迟渲染模式下正常工作。
2)顶点片段着色器:非常灵活地实现需要的效果,但是需要编写更多的代码,并且很难与Unity的渲染管线完美集成。
3)固定功能管线着色器:可以作为前两种备用选择,当硬件无法运行那些酷炫Shader时,还可以绘制出一些基本的内容。
渲染管道
是指在显示器上为了显示出图像而经过的一系列必要操作。 渲染管道中的很多步骤,都要将几何物体从一个坐标系中变换到另一个坐标系中去。
本地坐标->视图坐标->背面裁剪->光照->裁剪->投影->视图变换->光栅化。
水面倒影的渲染原理
原理就是对水面的贴图纹理进行扰动,以产生波光玲玲的效果。用shader可以通过GPU在像素级别作扰动,效果细腻,需要的顶点少,速度快【怎么把水面上的东西倒影在水面上:用Rendertexture/水下放一个对称的摄像机/模版测试】
怎么保证A组物体永远比B组物体先渲染
把A组物体的渲染对列大于B物体的渲染队列
GUI层级和深度问题
王者荣耀英雄展示界面怎么实现的
额外一个摄像机ModelCamera专门渲染要显示的模型。设置模型的Layer层为Model,随便定义。然后在我们主相机上,设置Culling mask去掉Model层
然后设置另一个ModelCamera的Clear Flags为Depth Only。代表只渲染指定层级的物体。然后设置Culling mask在Model上勾选,其他全部取消勾选。这样代表此相机只渲染Model层的物体。
BSP树和八叉树
(吃鸡里如何进行场景加载优化:场景剔除/八叉树)
BSP适用于室内小场景,八叉树适用于室外三维大场景。
BSP适合排序,内存耗费小,灵活,无效区域较小;大部分场景下更为平衡,还可以顺便执行碰撞检测。
做网格模拟流体的时候,用八叉树比较直接(八叉建立速度更快,因为分割规则是定的;而BSP树似乎分割好之后的均匀度比较好)。
四叉树和八叉树基本上是一样的,就是带不带高度或深度轴而已。为了实现和性能会规定最大递归深度。
C#的GC
工作原理:Garbage Collector以应用程序的root为基础,遍历应用程序在Heap上动态分配的所有对象,通过识别是否被引用来确定哪些对象已经死亡/仍要被使用。已经不再被引用的对象就是已经死亡,即垃圾,需要被回收。GC有多种算法:Reference Counting,Mark Sweep,Copy Collection...目前主流的虚拟系统.NET CLR,Java VM和Rotor都是采用的Mark Sweep算法。
Unity如何实现平滑运动
小红点系统如何设计
实时点光源的优缺点
可以有cookies–带有 alpha通道的立方图(Cubemap )纹理。点光源最耗费资源
Camera组件的ClearFlags选项选成Depth only
仅深度,该模式用于对象不被裁剪。
U3D是否支持多线程程序
仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用
支持:如果同时你要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine。
注意:C#中有lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象
U3D的协程和C#线程之间的区别
多线程程序同时运行多个线程 ,而在任一指定时刻只有一个协程在运行,并且这个正在运行的协同程序只在必要时才被挂起。
除主线程之外的线程无法访问Unity3D的对象、组件、方法。
Unity3d没有多线程的概念,不过unity也给我们提供了StartCoroutine(协同程序)和LoadLevelAsync(异步加载关卡)后台加载场景的方法。 StartCoroutine所谓协同,就是当StartCoroutine的函数体里处理一段代码时,利用yield语句等待执行结果,这期间不影响主程序的继续执行,可以协同工作。
矩阵相乘的意义及注意点
用于表示线性变换:旋转、缩放、投影、平移、仿射
注意矩阵的蠕变:误差的积累
MipMap定义与作用
贴图渲染中有常用的技术,为加快渲染进度和减少图像锯齿,贴图被处理成由一系列被预先计算和优化过的图片组成的文件,这样的贴图被称为MipMap。在三维计算机图形的
如何优化内存
有很多种方式,例如 1.压缩自带类库; 2.将暂时不用的以后还需要使用的物体隐藏起来而不是直接Destroy掉; 3.释放AssetBundle占用的资源; 4.降低模型的片面数,降低模型的骨骼数量,降低贴图的大小; 5.使用光照贴图,使用多层次细节(LOD),使用着色器(Shader),使用预设(Prefab)。
物理更新(固定物理帧FixedUpdate)
渲染帧执行,每固定帧绘制时执行一次,渲染效率低下的时候调用次数就会下降;
适用于物理引擎的计算,因为是跟每帧渲染有关。而Update就比较适合做控制。
U3D中的碰撞器和触发器的区别?
碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性。
当Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/Stay/Exit函数;
当Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用OnTriggerEnter/Stay/Exit函数。
如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件是否经过空间中的某个区域这时就可以用到触发器。
物体发生碰撞的必要条件?
两个物体都必须带碰撞器Collider,其中一个物体还必须带有Rigidbody刚体。
CharacterController和Rigidbody的区别?
Rigidbody具有完全真实物理的特性,而CharacterController可以说是受限的的Rigidbody,具有一定的物理效果但不是完全真实的。
碰撞过程中的几个阶段
OnCollision(Enter/Stay/Exit)
当细小高速物体撞向另一个较大的物体时?
穿透(碰撞检测失败)
Unity3d的物理引擎中,有几种施加力的方式,分别描述出来
rigidbody.AddForce、 rigidbody.AddForceAtPosition
Unity提供了几种光源,分别是什么?
四种。 平行光:Directional Light 点光源:Point Light 聚光灯:Spot Light 区域光源:Area Light
动态加载资源的方式?
1.Resources.Load(); 2.AssetBundle
什么是LightMap?
LightMap:就是指在三维软件里实现打好光,然后渲染把场景各表面的光照输出到贴图上,最后又通过引擎贴到场景上,这样就使物体有了光照的感觉。
LOD是什么,优缺点是什么?
LOD(Level of detail)多层次细节,是最常用的游戏优化技术。它按照模型的位置和重要程度决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。
在不同工程间安全地迁移asset数据
1.Assets和Library一起迁移2.导出包package 3.unity自带的assets Server
移动相机动作在哪个函数里,为什么在这个函数里?
LateUpdate,是在所有的Update结束后才调用,比较适合用于命令脚本的执行。官网上例子是摄像机的跟随,都是所有的Update操作完才进行摄像机的跟进,不然就有可能出现摄像机已经推进了,但是视角里还未有角色的空帧出现。
不同分辨率下保持UI的一致性
NGUI很好的解决了这一点,屏幕分辨率的自适应性,原理就是计算出屏幕的宽高比跟原来的预设的屏幕分辨率求出一个对比值,然后修改摄像机的size。
动态合批与静态合批
如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行批处理。动态批处理操作是自动完成的,并不需要你进行额外的操作。
区别:动态批处理一切都是自动的,不需要做任何操作,而且物体是可以移动的,但是限制很多。静态批处理:自由度很高,限制很少,缺点可能会占用更多的内存,而且经过静态批处理后的所有物体都不可以再移动了。
Interface与抽象类之间的不同
抽象类表示该类中可能已经有一些方法的具体定义,但接口就是公公只能定义各个方法的界面 ,不能具体的实现代码在成员方法中。
类是子类用来继承的,当父类已经有实际功能的方法时该方法在子类中可以不必实现,直接引用父类的方法,子类也可以重写该父类的方法。 实现接口的时候必须要实现接口中所有的方法,不能遗漏任何一个。
使用Unity3d实现2d游戏,有几种方式?
1.使用本身的GUI、UGUI
2.把摄像机的Projection(投影)值调为Orthographic(正交投影),不考虑z轴;
3.使用2d插件,如:2DToolKit、NGUI
物体自身旋转使用的函数——Transform.Rotate()
U3d保存和读取整形数据的函数
PlayerPrefs.SetInt()、 PlayerPrefs.GetInt()
客户端与服务器交互方式
socket通常也称作"套接字",实现服务器和客户端之间的物理连接,并进行数据传输,主要有UDP和TCP两个协议。Socket处于网络协议的传输层。
http协议传输的主要有http协议 和基于http协议的Soap协议(web service),常见的方式是 http 的post 和get 请求,web 服务。
.Net与Mono的关系?
mono是.net的一个开源跨平台工具,就类似java虚拟机,java本身不是跨平台语言,但运行在虚拟机上就能够实现了跨平台。.net只能在windows下运行,mono可以实现跨平台编译运行,可以运行于Linux,Unix,Mac OS等。
简述prefab的用处
在游戏运行时实例化,prefab相当于一个模板,对你已经有的素材、脚本、参数做一个默认的配置,以便于以后的修改,同事prefab打包的内容简化了导出的操作,便于团队的交流。
链条关节叫什么
Hinge Joint,可以模拟两个物体间用一根链条连接在一起的情况,能保持两个物体在一个固定距离内部相互移动而不产生作用力,但是达到固定距离后就会产生拉力。
在场景中放置多个Camera并同时处于活动状态会发生什么?
游戏界面可以看到很多摄像机的混合。
请描述游戏动画有哪几种,以及其原理?
主要有关节动画、骨骼动画、单一网格模型动画(关键帧动画)。 关节动画:把角色分成若干独立部分,一个部分对应一个网格模型,部分的动画连接成一个整体的动画,角色比较灵活,Quake2中使用这种动画;
骨骼动画,广泛应用的动画方式,集成了以上两个方式的优点,骨骼按角色特点组成一定的层次结构,有关节相连,可做相对运动,皮肤作为单一网格蒙在骨骼之外,决定角色的外观;
单一网格模型动画由一个完整的网格模型构成,在动画序列的关键帧里记录各个顶点的原位置及其改变量,然后插值运算实现动画效果,角色动画较真实。
alpha blend工作原理?
Alpha Blend实现透明效果,只能针对某块区域进行alpha操作,透明度可设。
写出光照计算中的diffuse的计算公式?
diffuse = Kd x colorLight x max(N*L,0);Kd 漫反射系数、colorLight 光的颜色、N 单位法线向量、L 由点指向光源的单位向量、其中N与L点乘,如果结果小于等于0,则漫反射为0。
两种阴影判断的方法、工作原理?
本影和半影:
本影:景物表面上那些没有被光源直接照射的区域(全黑的轮廓分明的区域)。
半影:景物表面上那些被某些特定光源直接照射但并非被所有特定光源直接照射的区域(半明半暗区域) 工作原理:从光源处向物体的所有可见面投射光线,将这些面投影到场景中得到投影面,再将这些投影面与场景中的其他平面求交得出阴影多边形,保存这些阴影多边形信息,然后再按视点位置对场景进行相应处理得到所要求的视图(利用空间换时间,每次只需依据视点位置进行一次阴影计算即可,省去了一次消隐过程)
Vertex Shader是什么,怎么计算?
顶点着色器是一段执行在GPU上的程序,用来取代fixed pipeline中的transformation和lighting,Vertex Shader主要操作顶点。
Vertex Shader对输入顶点完成了从local space到homogeneous space(齐次空间)的变换过程,homogeneous space即projection space的下一个space。在这其间共有world transformation, view transformation和projection transformation及lighting几个过程。
StringBuilder和String的区别
String是字符串常量。
StringBuffer是字符串变量 ,线程安全。
StringBuilder是字符串变量,线程不安全。
String类型是个不可变的对象,当每次对String进行改变时都需要生成一个新的String对象,然后将指针指向一个新的对象,如果在一个循环里面,不断的改变一个对象,就要不断的生成新的对象,所以效率很低,建议在不断更改String对象的地方不要使用String类型。
StringBuilder对象在做字符串连接操作时是在原来的字符串上进行修改,改善了性能。这一点我们平时使用中也许都知道,连接操作频繁的时候,使用StringBuilder对象。
Unity和cocos2d的区别
Unity3D支持C#、javascript等,cocos2d-x 支持c++、Html5、Lua等。
cocos2d 开源 并且免费
Unity3D支持iOS、Android、Flash、Windows、Mac、Wii等平台的游戏开发,cocos2d-x支持iOS、Android、WP等。
U3D中查看场景的面数/顶点数/Draw Call数(怎么降低Draw Call数)
在Game视图右上角点击Stats。降低Draw Call 的技术是Draw Call Batching
请问alpha test在何时使用?能达到什么效果?
Alpha Test,中文就是透明度测试。简而言之就是V&F shader中最后fragment函数输出的该点颜色值(即上一讲frag的输出half4)的alpha值与固定值进行比较。Alpha Test语句通常于Pass{}中的起始位置。Alpha Test产生的效果也很极端,要么完全透明,即看不到,要么完全不透明。
U3d在移动设备上的一些优化资源的方法
1)assetbundle实现资源分离和共享,将内存控制到200m之内,同时也可以实现资源的在线更新
2)顶点数对渲染无论是cpu还是gpu都是压力最大的贡献者,降低顶点数到8万以下,fps稳定到了30帧左右
3)只使用一盏动态光,不是用阴影,不使用光照探头,粒子系统是cpu大头
4)剪裁粒子系统,合并同时出现的粒子系统
5)把不需要跟骨骼动画和动作过渡的地方全部使用animation,控制骨骼数量在30根以下
6)删除无意义的animator且粒子上尽量不用它(初始化很耗时)
7)除主角外都不要跟骨骼运动apply root motion
编辑场景时将GameObject设置为Static
设置游戏对象为Static将会剔除(或禁用)网格对象当这些部分被静态物体挡住而不可见时。因此,在你的场景中的所有不会动的物体都应该标记为Static。
Texture和Sprite
Sprite作为UI精灵使用,Texture作用模型贴图使用。
一个Terrain,分别贴3/4/5张地表贴图,渲染速度有什么区别?
没有区别,因为不管几张贴图只渲染一次。
DrawCall?DrawCall高的影响?如何降低DrawCall?
Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。DrawCall越高对显卡的消耗就越大。降低DrawCall的方法:
Dynamic Batching、Static Batching
高级特性Shader降级为统一的低级特性的Shader。
NGUI中Grid和Table的作用?
对Grid和Table下的子物体进行排序和定位
只要提供一个half-pixel偏移量,它可以让一个控件的位置在Windows系统上精确的显示出来(只有这个Anchor的子控件会受到影响)
如果挂载到一个对象上,那么他可以将这个对象依附到屏幕的角落或者边缘
UIPanel用来收集和管理它下面所有widget的组件。通过widget的geometry创建实际的draw call。没有panel所有东西都不能够被渲染出来,你可以把UIPanel当做Renderer