unity面试问题收集

unity老版本只有Animation组件,后来版本增添了Animator,如果只是控制一个动画的播放我们则用Animation,如果需要多个动画之间的互相转换,我们则使用Adminitor组件,它们之间的区别是Animator有一个动画控制器,使用它来进行动画切换是非常方便的,但是缺点是占用的内存比Animation组件大

什么是DrawCall?DrawCall高了又什么影响?如何降低DrawCall?
Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。DrawCall越高对显卡的消耗就越大。降低DrawCall的方法:

  1. Dynamic Batching//动态批处理
  2. Static Batching//静态批处理
  3. 高级特性Shader降级为统一的低级特性的Shader。
  4. https://blog.csdn.net/u3d_ysj/article/details/47906035

UNITY3d在移动设备上的一些优化资源的方法
1.使用assetbundle,实现资源分离和共享,将内存控制到200m之内,同时也可以实现资源的在线更新
2.顶点数对渲染无论是cpu还是gpu都是压力最大的贡献者,降低顶点数到8万以下,fps稳定到了30帧左右
3.只使用一盏动态光,不是用阴影,不使用光照探头
粒子系统是cpu上的大头
4.剪裁粒子系统
5.合并同时出现的粒子系统
6.自己实现轻量级的粒子系统
animator也是一个效率奇差的地方
7.把不需要跟骨骼动画和动作过渡的地方全部使用animation,控制骨骼数量在30根以下
8.animator出视野不更新
9.删除无意义的animator
10.animator的初始化很耗时(粒子上能不能尽量不用animator)
11.除主角外都不要跟骨骼运动apply root motion
12.绝对禁止掉那些不带刚体带包围盒的物体(static collider )运动
NGUI的代码效率很差,基本上runtime的时候对cpu的贡献和render不相上下
13每帧递归的计算finalalpha改为只有初始化和变动时计算
14去掉法线计算
15不要每帧计算viewsize 和windowsize
16filldrawcall时构建顶点缓存使用array.copy
17.代码剪裁:使用strip level ,使用.net2.0 subset
18.尽量减少smooth group
19.给美术定一个严格的经过科学验证的美术标准,并在U3D里面配以相应的检查工具

1.assetbundle实现资源的分离和共享,将内存控制在200m以内,同时实现资源的在线更新。
2.降低顶点数
3.只使用一盏动态灯,不使用阴影
4.裁剪粒子系统,合并同时出现的粒子系统,自己实现轻量级的粒子系统
5.如果可以用animation代替animator的地方尽量代替,animator出了视野不更新,删除无意义的animator,粒子尽量不要用animator
6.去掉法线计算
7.不要每帧计算viewsize和windowsize

七层协议:
最下面一层是物理层,关心的是接口,信号,和介质,只是说明标准,如EIA-232接口,以太网,fddi令牌环网
第二层是数据链路层:一类是局域网中数据连路层协议:MAC子层协议,有LLC子层协议.另一类是广域网的协议如:HDLC,PPP,SLIP.
第三层是网络层:主要是IP协议.
第四层是传输层:主要是面向连接的TCP传输控制协议.另一个是不面向连接的UDP用户数据报协议
第五层是会话层:主要是解决一个会话的开始进行和结束.(真的想不起有什么协议)
第六层是表示层:主要是编码如ASⅡ
第七层是应用层,就是应用程序里面的拉,文件传输协议FTP、电子邮件传输协议SMTP、域名系统服务DNS、网络新闻传输协议NNTP和HTTP协议等。 HTTP协议(Hypertext Transfer Protocol,超文本传输协议)是用于从WWW服务…

客户端与服务器交互方式有几种?
socket通常也称作”套接字”,实现服务器和客户端之间的物理连接,并进行数据传输,主要有UDP和TCP两个协议。Socket处于网络协议的传输层。
http协议传输的主要有http协议 和基于http协议的Soap协议(web service),常见的方式是 http 的post 和get 请求,web 服务。

概述c#中委托和事件?
委托就是用来定义指向方法的引用。
C#事件本质就是对消息的封装,用作对象之间的通信;发送方叫事件发送器,接收方叫事件接收器
http://www.tracefact.net/tech/009.html

Heap与Stack有何区别?
1.heap是堆,stack是栈。
2.stack的空间由操作系统自动分配和释放,heap的空间是手动申请和释放的,heap常用new关键字来分配。
3.stack空间有限,heap的空间是很大的自由区。

Unity3D Shader分哪几种,有什么区别?
表面着色器Surface Shader的抽象层次比较高,它可以轻松地以简洁方式实现复杂着色。表面着色器可同时在前向渲染及延迟渲染模式下正常工作。
顶点片元着色器Vertex/Fragment Shader可以非常灵活地实现需要的效果,但是需要编写更多的代码,并且很难与Unity的渲染管线完美集成。
固定功能管线着色器Fixed Function Shader可以作为前两种着色器的备用选择,当硬件无法运行那些酷炫Shader的时,还可以通过固定功能管线着色器来绘制出一些基本的内容。

foreach是只读的。不能一边遍历一边修改。

C#的委托是什么?有何用处?
委托类似于一种安全的指针引用,在使用它时是当做类来看待而不是一个方法,相当于对一组方法的列表的引用。用处:使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象,而且是类型安全的。

什么是渲染管道?
渲染管道就是显示器为了显示图像而进行的一系列必要的操作。在渲染管道中,这些操作很多都是从一个坐标系转换到另一个坐标系。大概可以分为以下的流程:本地坐标-》视图坐标-》背面裁剪-》光照-》裁剪-》投影-》视图变换-》光栅化

请简述c#值类型与引用类型的区别
1.值类型存储在内存栈中,引用类型数据存储在内存堆中,实际存放的是内存堆中对象的地址。 (值类型存储在栈中,引用类型数据存储在堆中)
2.值类型存取快,引用类型存取慢。 (值类型存取快,引用类型存取慢)
3.值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针或引用。 (值类型是实际的数据,引用类型是指向内存堆中数据的指针或者引用)
4.栈的内存是自动释放的,堆内存是.NET中会由GC来自动释放。 (栈的内存是自动释放的,堆的内存需要GC来释放,C和C++中则需要自己释放)
5.值类型继承自System.ValueType(它的父类是System.Object),引用类型继承自System.Object。(值类型继承于System.ValueType(它的父类是System.Object),引用类型是继承自System.Object)
值类型:byte,int,short,long,char,float,double,bool,枚举:enum,结构体:struct
引用类型:类,接口,委托,object,string(值类型:我们常用的数值类型,需要注意的是枚举enum,结构体struct。引用类型:类,接口,委托,object,string)

请简述ArrayList和List的主要区别
ArrayList存在不安全类型(ArrayList会把所有插入其中的数据都当做Object来处理) 同时多次的装箱拆箱操作很耗时间。
List则引入了泛型的概念,按照所需要的类型进行存储,减少了拆箱的操作,节省了系统资源,减少了性能损耗。
装箱是指由值类型转换成引用类型的过程,拆箱是指由引用类型转换成值类型的过程

log和mipmap的区别
log是多层次图像处理,mipmap是预先模糊处理,用来预先渲染。

请简述GC(垃圾回收)产生的原因,并描述如何避免?
GC回收堆上的内存
避免:
1)减少new产生对象的次数
2)使用公用的对象(静态成员),但是静态对象会一直存在,直到退出程序
3)将String换为StringBuilder

C#中所有引用类型的基类是什么
引用类型的基类是System.Object 值类型的基类是System.ValueType
同时,值类型也隐式继承自System.Object

请描述Interface与抽象类之间的不同
接口中所有的方法都不能有实现,并且不能指定方法的修饰符
抽象类中可以有方法的实现,也可以指定方法的访问修饰符
第一个继承接口的类必须实现接口里的所有方法
抽象类的子类还是派生类都是可以不实现父类中的抽象方法

请简述关键字Sealed(秀得)用在类声明和函数声明时的作用
修饰类时可防止其他类继承此类
修饰方法时则可防止派生类重写此方法

Unity3D是否支持写成多线程程序?如果支持的话需要注意什么?
Unity3D只有协程,没有多线程。
要注意得是:我们只能在主线程中访问Unity3D的组件,对象和Unity3D系统调用 。

Unity3D的协程和C#线程之间的区别是什么?

多线程程序同时运行多个线程 。
而在任一指定时刻只有一个协程在运行,并且这个正在运行的协同程序只在必要时才被挂起,不影响主程序的运行。除主线程之外的线程无法访问Unity3D的对象、组件、方法。
(unity3d没有多线程得概念,但是它有一个协同程序(StartCoroutine)和一个异步加载场景(LoadLevelAsync))
Unity3d没有多线程的概念,不过unity也给我们提供了StartCoroutine(协同程序)和LoadLevelAsync(异步加载关卡)后台加载场景的方法。 StartCoroutine为什么叫协同程序呢,所谓协同,就是当你在StartCoroutine的函数体里处理一段代码时,利用yield语句等待执行结果,这期间不影响主程序的继续执行,可以协同工作。而LoadLevelAsync则允许你在后台加载新资源和场景,所以再利用协同,你就可以前台用loading条或动画提示玩家游戏未卡死,同时后台协同处理加载的事宜 Asynchronous同步。

U3D中用于记录节点空间几何信息的组件名称,及其父类名称
组件是Transform ,它的父类是 Component

简述四元数的作用,四元数对欧拉角的优点?
四元数用于表示旋转
相对欧拉角的优点:
1)能进行增量旋转,两个四元数相乘可表示两次旋转。
2)避免万向锁问题
https://blog.csdn.net/qq_35957011/article/details/77188036
3)给定方位的表达方式有两种,互为负(欧拉角有无数种表达方式)
4)可以平滑插值
https://blog.csdn.net/candycat1992/article/details/41254799
https://blog.csdn.net/a117653909/article/details/49305357
函数
https://blog.csdn.net/yustarg/article/details/8623687

向量的点乘、叉乘以及归一化的意义?
1)点乘描述了两个向量的相似程度,结果越大两向量越相似,还可表示投影
2)叉乘得到的向量,这个向量垂直于原来的两个向量,可以用来求平面法线
3)(归一化)标准化向量:用在只关系方向,不关心大小的情况

矩阵相乘的意义及注意点
用于表示线性变换:旋转、缩放、投影、平移等。
注意矩阵的蠕变:误差的积累,进行线性变换时误差会越来越大

为何大家都在移动设备上寻求U3D原生GUI的替代方案
OnGUI很耗费时间(每帧调用2次,频率是Update的2倍),使用不方便 ,DrawCall更高

请简述如何在不同分辨率下保持UI的一致性
NGUI很好的解决了这一点,屏幕分辨率的自适应性,原理就是计算出屏幕的宽高比跟原来的预设的屏幕分辨率求出一个对比值,然后修改摄像机的size。
UGUI中,CanvansScaler中的UI Scale Mode可以选择支持UI的适配方式(UGUI里面canvas得设置中可以选择屏幕自适应)

在场景中放置多个Camera并同时处于活动状态会发生什么?
实际看到的画面由多个camera的画面组成,由depth、Clear Flag、Culling Mask都会影响最终合成效果。

Prefab的作用?如何在移动环境的设备下恰当地使用它?
在游戏运行时实例化,prefab相当于一个模板,对已有得素材,脚本,参数做了一个默认得配置,方便我们使用和修改,prefab得打包也简化了导出得操作,便于团队交流)

如何安全的在不同工程间安全地迁移asset数据?三种方法
1.将Assets目录和Library目录一起迁移
2.导出包
3.用unity自带的assets Server功能

MeshCollider和其他Collider的一个主要不同点?
Meshcollider是基于Vector3顶点, Collider本身是基于算法,没有面的概念

当一个细小的高速物体撞向另一个较大的物体时,会出现什么情况?如何避免?
穿透现象(碰撞检测失败)
解决方法:

  1. 增大细小物体的碰撞体
  2. 使用射线检测 (主要解决)
  3. 可以physics time减小,不建议这样做
  4. 确保rigidbody不超过一定的速度,这个也不实用

31.OnEnable、Awake、Start运行时的发生顺序?哪些可能在同一个对象周期中反复的发生?
Awake —>OnEnable—>Start
OnEnable时可以在同一个周期反复发生的。

Unity3D 中动态加载资源有几种方法,分别是什么?
 通过Resources模块,调用它的load函数:可以直接load并返回某个类型的Object,前提是要把这个资源放在Resource命名的文件夹下,Unity不管有没有场景引用,都会将其全部打入到安装包中。
 通过bundle的形式:即将资源打成 asset bundle 放在服务器或本地磁盘,然后使用WWW模块get 下来,然后从这个bundle中load某个object。
 通过AssetDatabase.loadasset :这种方式只在editor范围内有效,游戏运行时没有这个函数,它通常是在开发中调试用的
(1.Resources.load()加载一些放在Resources文件夹下的资源,Unity不管有没有场景引用,都会把文件夹下的全部打入到安装包中
2.assetbundle:把资源打包成assetbundle放在服务器或者本地,然后通过WWW模块get下来,然后就可以从这个bundle中load某一个object。)

u3d中碰撞器和触发器的区别?
collider碰撞器是会产生碰撞效果的,IsTrigger必须为false,可以调用OnCollisionEnter/Stay/Exit函数。参数为collision
碰撞条件:
1 碰撞双方必须是碰撞体
2 碰撞的主动方必须有刚体,注意我的用词是主动方,而不是被动方
3 刚体不能勾选IsKinematic
4 碰撞体不能够勾选IsTigger
trigger触发器时没有碰撞效果的,isTrigger必须为true,可以调用OnTriggerEnter/Stay/Exit函数,参数为collider
https://blog.csdn.net/tianyao9hen/article/details/53141141

CharacterController(第一人称控制器)和Rigidbody的区别
Rigidbody具有完全真实物理的特性,而CharacterController可以说是受限的Rigidbody,具有一定的物理效果但不是完全真实的。

u3d中,几种施加力的方式,描述出来。
rigidbody.AddForce/AddForceAtPosition,都是rigidbody的成员函数

什么叫做链条关节
Hinge Joint ,他可以模拟两个物体间用一根链条连接在一起的情况,能保持两个物体在一个固定距离内部相互移动而不产生作用力,但是达到固定距离后就会产生拉力。(简单说就是弹簧)

物体自旋转使用的函数叫什么
transform.Rotate

物体绕某点旋转使用函数叫什么
transform.RotateAround

unity3d提供了几种光源,分别是什么
平行光:Directional Light
聚光灯:Spot Light
点光源:Point Light
区域光源:Area Light(只用于烘培)

unity3d从唤醒到销毁有一段生命周期,请列出系统自己调用的几个重要方法。
Awake –>OnEnable –> Start –> FixedUpdate –>Update –>LateUpdate –> OnGUI –>OnDisable –> OnDestroy

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

移动相机动作在哪个函数里,为什么在这个函数里。
LateUpdate,,是在所有update结束后才调,比较适合用于命令脚本的执行。官网上例子是摄像机的跟随,都是在所有update操作完才跟进摄像机,不然就有可能出现摄像机已经推进了,但是视角里还未有角色的空帧出现。

当游戏中需要频繁创建一个物体对象时,我们需要怎么做来节省内存。
做一个对象池,游戏开始时预先实例化足够的数量,然后用的时候取不用的时候收回

如何优化内存?
有很多种方式,例如
1.压缩自带类库;
2.将暂时不用的以后还需要使用的物体隐藏起来而不是直接Destroy掉;
3.释放AssetBundle占用的资源;
4.降低模型的片面数,降低模型的骨骼数量,降低贴图的大小;
5.使用光照贴图,使用多层次细节(LOD),使用着色器(Shader),使用预设(Prefab)。

写出Animation的五个方法
Animation.Play
Animation.CrossFade
Animation.Stop
Animation.Sample
Animation.AddClip

在类的构造函数前加上static会报什么错?为什么?
构造函数格式为 public+类名如果加上static会报错(静态构造函数不能有访问修饰符)
原因:静态构造函数不允许访问修饰符,也不接受任何参数;
无论创建多少类型的对象,静态构造函数只执行一次;
运行库创建类实例或者首次访问静态成员之前,运行库调用静态构造函数;
静态构造函数执行先于任何实例级别的构造函数;
显然也就无法使用this和base来调用构造函数。

C# String类型比stringBuilder类型的优势是什么?
如果是处理字符串的话,用string中的方法每次都需要创建一个新的字符串对象并且分配新的内存地址,而stringBuilder是在原来的内存里对字符串进行修改,所以在字符串处理方面还是建议用stringBuilder这样比较节约内存。但是string 类的方法和功能仍然还是比stringBuilder类要强。
string类由于具有不可变性(即对一个string对象进行任何更改时,其实都是创建另外一个string类的对象),所以当需要频繁的对一个string类对象进行更改的时候,建议使用StringBuilder类,StringBuilder类的原理是首先在内存中开辟一定大小的内存空间,当对此StringBuilder类对象进行更改时,如果内存空间大小不够,会对此内存空间进行扩充,而不是重新创建一个对象,这样如果对一个字符串对象进行频繁操作的时候,不会造成过多的内存浪费,其实本质上并没有很大区别,都是用来存储和操作字符串的,唯一的区别就在于性能上。
String主要用于公共API,通用性好、用途广泛、读取性能高、占用内存小。
StringBuilder主要用于拼接String,修改性能好。
不过现在的编译器已经把 String 的 + 操作优化成 StringBuilder 了,所以一般用String就可以了
String是不可变的,所以天然线程同步。
StringBuilder可变,非线程同步。

1.C#中类是否支持多继承?请说明原因。
答:不支持,需要用接口来实现多继承

2.我们都知道一个类可以有多个构造函数,并且C#会在我们创建类的时候默认的提供一个无参的构造函数,当我实现了另外一个有参数的构造函数的时候,我还能调用无参数的构造函数吗?请说明原因。
答:不能,因为一旦你实现了一个构造函数,C#就不会再提供默认的构造函 数了,所以需要自己手动写入一个无参数的构造函数。

3.请简略描述重载和重写的区别?
答:方法重载提供了一个相同的方法但是方法签名的参数不同的调用的实现。
重写提供了子类中改变父类方法行为的实现。

4.请问能设置类A可被继承,但类A中的某个方法不能被重写吗?
答:能,将类A的修饰符标记为public、标记类A中的不允许重写的方法为sealed
sealed关键字不仅可以限制类,也可以限制方法。

5.const和readonly有什么区别?
答:const关键字用来声明编译时的常量
readonly用来声明运行时的常量

6.什么时候必须声明一个类为抽象类?
答:(1)当这个类中有抽象方法的时候,必须声明类为抽象类
(2)该类没有完全实现父类的抽象方法时,也需要声明为抽象类

7.接口和抽象类的区别是什么?
答:接口中所有的方法都不能有实现,并且不能指定方法的修饰符
抽象类中可以有方法的实现,也可以指定方法的访问修饰符
第一个继承接口的类必须实现接口里的所有方法
而抽象类中抽象方法的实现是由第一个非抽象的派生类来实现

8.类的私有成员会被子类继承吗?请说明原因。
答:会被子类继承,但是不能被访问。所以看上去是不能被继承的,实际上确实被继承了。

9.请写出C#中的单例模式
答:
public class Single
{
private static Single instance;
private Single (){}
public static Single GetInstance ()
{
if (instance == null) {
instance = new Single ();
}
return instance;
}
}
14.射线检测碰撞物体的原理是什么?

射线是3D世界中一个点向另一个方向发射的一条无终点的线,在发射轨迹中与其他物体发生碰撞时,它将停止发射。

15.如何让已存在的GameObject在场景加载之后不被卸载掉?

gameobject.DontDestroyOnLoad()

16.请说明transform.parent和transform.SetParent的区别

parent可以get和set;SetParent只能set

17.unity提供了4种光源,平行光Derectional Light;点光源Point Light;区域光源Area Light;聚光源Spot Light

18.物理更新放在FixUpdate中比较合适,按照固定时间执行,默认0.02S

19.获取的命令时GetComponent,增加是AddComponent,Destroy删除

20.请简述AnimatorController中的Has Exit Time的作用是什么。

当我们勾选了此项,在动画转换时会等待当前动画播放完毕后才会才会转换到下一个动画,如果当前动画时循环动画会等待本次播放完毕转换,所以对需要立即转换动画的情况下一定要取消勾选此项;

还有一种情况时,当前动画播放完毕后会自动转换到箭头所指的下一条状态(没有其它条件时),此时必须勾选此项,否则动画播放完毕后会卡在最后一帧,如果是循环动画,则会一直循环播放。

21.链表和数组的区别
二者都属于同一种数据结构
从逻辑结构上来看:

1.数组申请的是一块连续的内存空间,编译阶段就确定了空间大小,是不允许改变的,不能适应数据动态的增减的情况。当数据增加时,可能会会超出原先定义的数组个数,造成数据越界;当数据减少时,造成资源浪费。

2.链表动态地进行存储分配,现用现申请,可以适应数据动态增减的情况,且可以方便地插入删除数据项。(数组中插入和删除数据项时,需要移动其他的数据项,非常繁琐)链表必须根据next指针找到下个元素

从内存存储上来看:

1.数组从栈中分配空间,对于程序员方便快速,但是自由度小,数组可以根据下标直接存储数据。如果数组中需要增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放入其中。同样的道理,如果想要删除一个元素,需要移动大量的元素去填掉被移动的元素。如果需要快速访问数据,很少或不插入或删除元素,应使用数组。

2.链表从堆中分配空间,自由度大但是申请管理比较麻烦,链表是物理上非连续的内存空间,对于访问数据,需要从头遍历整个链表直到找到要访问的数据,没有数组有效,但是在添加和删除数据方面,只要知道操作位置的指针,很方便实现增删,较数组比较灵活youxiaolv。

从上面可以看出,如果经常访问数组,而很少增加和删除数据,可以用数组;如果经常增加和删除数据,用链表。

22.用sealed修饰的类有什么特点?

无法作为其他类的父类,不能含有虚方法和抽象方法;当sealed修饰方法时,该方法不能被子类重写。

23.MVC模式,M,V,C分别代表什么?

MVC是model-view-controller的缩写,模型-视图-控制器

M是数操作数据逻辑的部分,V是显示的应用模型数据或交互界面,C是程序的视图和操作逻辑的协调者。

24.类和结构体的区别

1.类是引用类型,结构体是值类型。

2.结构体和类初始化都使用了new,但一个是分配在堆上,一个在栈上。

3.结构体是隐式的sealed,不能被继承,也不能从另一个类或结构体继承;类可以。

当处理数量小的场合使用结构体比较好;对于大量的逻辑对象,使用类比较好。

1.GameObject和transform.Find的区别。

GameObject通过名字或者路径来查找游戏对象:GameObject.Find(“a”)
(1)无法查找隐藏对象。在查找路径上任意一个父物体隐藏都查不到
(2)如果查找不在最上层,就需要根据路径查找,但路径查找是把双刃剑
优点1:解决查找中可能出现的重名问题
优点2:如果有完全的路径,减少查找范围,减少查找时间
缺点:结构或路径调整后,容易影响到物体的查找,需要重新定位查找路径
(3)使用方便但效率低下。
此查找相当于递归遍历查找,虽然操作方便,但效率低下,建议在start中查找对象并保存引用,切忌在update中动态查找。
transform.Find
(1)可以查找隐藏对象
(2)支持路径查找
(3)查找隐藏对象的前提是transform所在的根节点必须可见,即active=true

**其他查找:
GameObject.FindWithTag
GameObject.FindGameObjectsWithTag
**隐藏根节点也可查找:使用Resouces.FindObjectsOfTypeAll

2.物体自身旋转使用的函数是Transform.Rotate;围绕一个物体旋转使用的函数是Transform.RotateAround

3.unity中使用LitJSON,将对象转化成字符串使用JsonMapper.ToJson();将字符串转换成对象使用JsonMapper.ToObject()

4.简述一下什么是GC,GC的流程
GC:垃圾回收器
流程:标记,计划和清理,引用更新和压缩

猜你喜欢

转载自blog.csdn.net/qq842447820/article/details/82225374