Unity客户端开发面试题记录

Unity客户端开发面试题记录

1.如何理解面向对象思想
A:面向对象是将功能等通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节。面向对象的特征是:封装,继承,多态。多态就是接口的多种不同的实现方式。

2.默认构造方法可以重写吗
A:不能。

3.Sealed在声明类和函数方法时代表什么
A:在类声明中使用sealed可防止其它类继承此类;在方法声明中使用sealed修饰符可防止扩充类重写此方法。

4.什么是装箱和拆箱
A:
在这里插入图片描述

5.ref参数和out参数是什么,有什么区别
A:ref
在这里插入图片描述
在这里插入图片描述
out
在这里插入图片描述
在这里插入图片描述
ref和out都是通过关键字找到定义在主函数里面的变量的内存地址,并通过方法体内的语法改变它的大小。
ref将参数的参数值和引用都传入方法中,所以ref的参数的初始化必须在方法外部,否则程序报错,ref参数是引用。
out不会将参数的参数值传入方法中,只会将参数的引用传入方法中,所以out的参数的初始化必须在方法中进行,否则报错,out参数为输出参数。

6.请简述private,public,protected,internal的区别
A:
public:对任何类和成员都公开,无限制访问
private:仅对该类公开
protected:对该类和其派生类公开
internal:只能在包含该类的程序集中访问该类

7.物理更新一般放在哪个系统函数里
A:FixedUpdate,每固定帧绘制时执行一次,和Update不同的是FixedUpdate是渲染帧执行,FixedUpdate比较适用于物理引擎的计算。

8.结构体和类有何区别
A:结构体是一种值类型,而类是引用类型。

9.移动相机动作在哪个函数里,为什么在这个函数里
A:在LateUpdate,是在所有的update结束后才调用,比较适合用于命令脚本的执行。

10.如下函数方法最后输出结果是什么
在这里插入图片描述
A:运行顺序为1,3,4,5,6,无论try或者catch是否return,finally必然执行,输出为3。

11.override和overload的区别
A:
override表示重写,用于继承类对基类中虚成员的实现
overload表示重载,用于同一个类中同名方法不同参数(包括类型不同或个数不同)的实现

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

13.简述prefab的用处
A:在游戏运行实例化,perfab相当于一个模板,对你已经有的素材,脚本,参数做一个默认的配置,以便于以后的修改,同时prefab打包的内容简化了导出的操作,便于团队的交流。

14.如何降低包的体积
A:
1.替换jpg,使用psd,减少重复资源
2.剔除不必要的资源
3.打包时查看log记录,由此判断需要减少的文件类型
4.压缩图片,减少图片大小
5.压缩网格和动画,减少文件大小
6.剔除system.dll和system.xml.dll

15.不使用第三方变量交换a和b
A:
在这里插入图片描述

16.编程求两个数的最小公倍数和最大公约数
A:
在这里插入图片描述

17.用递归和非递归求斐波那契数列第30项的值
A:递归算法:
在这里插入图片描述
一般算法:
在这里插入图片描述
18.i++和++i命令的区别
A:赋值顺序不同,++i是先加后赋值;i++是先赋值后加。

19.列举熟悉的数据结构
A:数组,栈,队列,链表,树,图,堆。

20.简述值类型和引用类型有什么区别
A:
1.值类型存储在内存栈中,引用类型存储在内存堆中,而内存单元中存放的是堆中存放的地址。
2.值类型存取快,引用类型存取慢。
3.值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针和引用。
4.栈的内存是自动释放的,堆内存是.Net中会由GC来自动释放。
5.值类型继承自System.ValueType,引用类型继承自System.Object。

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

22.请简述ArrayList和List<>的主要区别
A:ArrayList不带泛型,数据类型丢失;List带泛型,数据类型不丢失;ArrayList需要装箱拆箱,List不需要。

23.请简述GC(垃圾回收)产生的原因,并描述如何避免?
A:GC为了避免内存溢出而产生的回收机制,避免:
(1)减少new产生对象的次数
(2)使用公开的对象(静态成员)
(3)将String换为StringBuilder

24.简述Interface与抽象类之间的不同
A:
1.接口类不是类,不能实例化,抽象类可以间接实例化
2.接口是完全抽象,抽象类为部分抽象
3.接口可以多继承,抽象类是单继承

25.反射的实现原理
A:可以在加载程序运行时,动态获取和加载程序集,并且可以获取到程序集的信息反射即在运行期动态获取类、对象、方法、对象数据等的一种重要手段。主要使用的类库:System.Reflection
核心类:
1.Assembly描述了程序集
2.Type描述了类这种类型
3.ConstructorInfo描述了构造函数
4.MethodInfo描述了所有的方法
5.FieldInfo描述了类的字段
6.PropertyInfo描述类的属性
通过以上核心类可在运行时动态获取程序集中的类,并执行类构造产生类对象,动态获取对象的字段或属性值,更可以动态执行类方法和实例方法等。

26…Net与Mono的关系?
A:.Net是一个语言平台,Mono为.Net提供继承开发环境,集成并实现了.Net的编译器、CLR和基础类库,使得.Net既可以运行在Windows也可以运行与Linux,Unix,Mac OS等。

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

28.C#String类型比stringBuilder类型的优势是什么?
A:
1.在处理字符串中:string是创建一个string对象,在创建对象时需要分配内存空间。stringBuilder是在原来的内存中修改,不需要分配内存空间。
2.从内存优化方面来说,频繁对字符串的操作使用StringBuilder更好。
3.从功能上来说String仍然比StringBuilder更强。
4.String主要用于公共API,通用性好,读取性能高,占用内存小。
5.StringBuilder主要用于拼接String,修改性能好。
6.string是不可变的,所以天然线程同步;stringBuilder可变,非线程同步。

29.数列1,1,2,3,5,8,13…第n位数是多少?用C#递归算法实现
A:
在这里插入图片描述

30.冒泡排序代码
A:
public static void BubblingSort(int[] array){for (int i = 0; i < array.Length - 1; i++){int temp = 0;for (int j = 0; j < array.Length - i - 1; j++){if (array[j] > array[j + 1]){temp = array[j];array[j] = array[j + 1];array[j + 1] = temp;}}}}

31.C#中有哪些常用的容器类,各有什么特点。
A:List,HashTable,Dictionary,Stack,Queue
List:索引泛型容器,访问速度快,修改速度慢
HashTable/Dictionary:散列表格式,查询效率高,空间占用率大
Stack:后进先出
Queue:先进先出

32.C#中常规容器和泛型容器有什么区别,那种效率高?
A:不带泛型的容器需要装箱和拆箱操作,速度慢,所以泛型容器效率更高,数据类型更安全

32.C#中委托和接口有什么区别?各用在什么场合?
A:接口是约束类应该具备的功能集合,约束了类应该具备的功能,使类从千变万化的具体逻辑中解脱出来,便于类的管理和扩展,同时又合理解决了类的单继承问题。
委托是约束方法集合的一个类,可以便捷的使用委托对这个方法集合进行操作。
在以下情况中使用接口:
1.无法使用继承的场合
2.完全抽象的场合
3.多人协作的场合
以上等等
在以下情况中使用委托:多用于事件处理中

33.有哪些常见的数值类
A:简单值类型–包括 整数类型、实数类型、字符类型、布尔类型
复合值类型–包括 结构类型、枚举类型

34.C#中unsafe关键字是用来做什么的?在什么场合使用?
A:非托管代码才需要这个关键字,一般用在带指针操作的场合

35.For,foreach,Enumerator.MoveNext的使用,与内存消耗情况
A:for循环可以通过索引依次进行遍历,foreach和Enumerator.MoveNext通过迭代的方式进行遍历。内存消耗上本质上并没有太大的区别。但是在Unity中的Update中,一般不推荐使用foreach,因为会遗留内存垃圾。

36.函数中多次使用string的+=处理,会产生大量内存垃圾(垃圾碎片),有什么好的方法可以解决。
A:通过StringBuilder那进行append,这样可以减少内存垃圾。

37.当需要频繁创建使用某个对象时,有什么好的程序设计方法来节省内存?
A:设计单例模式进行创建对象或使用对象池

38.JIT和AOT区别
A:Just-In-Time:实时编译
执行慢,安装快,占空间小一点
Ahead-Of-Time-预先编译
执行快,安装慢,占内存占外存大

39.给定一个存放参数的数组,重新排列数组
A:void SortArray(Array arr){
Array.Sort(arr);
}

40.foreach循环迭代时,若把其中的某个元素删除,程序报错,怎么找到那个元素?以及具体怎么处理这种情况?(注:Try…Catch捕捉异常,发送信息不可行)
A:foreach不能进行元素的删除,因为迭代器会锁定迭代的集合,解决方法:记录找到索引或者Key值,迭代结束后再进行删除。

41.GameObject a=new GameObject() GameObject b=a 实例化出来了A,将A赋给B,现在将B删除,请问A还存在吗?
A:存在,b删除只是将它在栈中的内存删除,而A对象本身是在堆中,所以A还在。

42.你拥有A块钱,一瓶水B块钱,每瓶水可以得到一个瓶盖,每C个瓶盖可以换一瓶水,请写出函数求解上面题目,上面题目ABC为参数
A:
public static int Buy(int a,int b,int c){
return a/b+ForCap(c,a/b);
}

public static int ForCap(int c,int d){
if(d<c){
return 0;
}else{
return d/c+ForCap(c,d/c+d%c);
}
}

43.有一排开关,第一个人把所有的开关打开,第二个人按2的倍数的开关,第三个人按3的倍数的开关,以此类推,现在有n个开关,k个人,写函数求最后灯亮着的开关,输入参数n和k
A:
static void Function(int n,int k){
int i,j=0;
bool []a=new bool[1000]; //初始false:关灯,true:开灯
for(i=1;i<=k;i++) { //k个人
for(int j=1;j<=n;j++){ //n个灯
if(j%i==0)
a[j]=!a[j]; //取反,false变true,原来开变关,关变开
}
for(int i=1;i<=n;i++){
if(a[i]){ //灯亮着
Console.WriteLine(i);
}
}
}
}
}

44.数值转换,将任意整数转换成8进制形式
A:
static void d2o(int n){
if(n>7){
d2o(n/8);
}
Console.Wirte(n%8);
}

45.找出200以内的素数
A:
int count=0;for(int i=1;i<200;i++){for(int j=2;j<=i;j++){if(i%j==0&&i!=j){break;}if(j==i){count++;Console.WriteLine(i);}}}Console.WriteLine(count);

46.打印杨辉三角形
A:
在这里插入图片描述
在这里插入图片描述

47.请描述游戏动画有几种,以及其原理
A:主要有关节动画、关键帧动画,骨骼动画。
关节动画把角色分成若干独立部分,一个部分对应一个网格模型,部分的动画连接成一个整体的动画。
关键帧动画由一个完整的网格模型构成,在动画序列的关键帧里记录各个顶点的原位置及其改变量,然后插值运算实现动画效果,角色动画较真实。
骨骼动画,骨骼按角色特点组成一定的层次结构,由关节相连,可做相对运动,皮肤作为单一网格蒙在骨骼之外,决定角色的外观。皮肤网格每一个顶点都会受到骨骼的影响,从而实现完美的动画。

48.物体发生碰撞的条件
A:物体A必须带有(collider+rigidbody)或者CharacController,另一个物体也必须至少带有collider。

49.GUI与UGUI的优点和缺点
A:GUI不方便控制,UGUI所见即所得,方便控制。GUI使用在生命周期函OnGUI中使用,脚本来书写控制。UGUI使用Canvas画布和事件系统,UGUI适应屏幕上比GUI简单。

50.一个场景放置多个Camera并同时处于活动状态,会发生什么?
A:实际看到的画面由多个Camera的画面组成,由depth、Clear Flag、Culiing Mask都会影响最终合成结果。

51.使用过哪些第三方插件
A:
界面制作:NGUI
2D游戏制作:2D Toolkit
可视化编程:PlayMaker
插值插件:iTween
路径搜寻:Simple Path
美术及动画制作:Smooth Moves
画面增强:Strumpy Shader Editor
摄像机管理:Security Camera
资源包:Nature Pack
造路插件:EasyRoads3D

52.U3D中用于记录节点空间几何信息的组件名称,及其父类名称
A:TransForm,父类是Componet。

53.为何大家都在移动设备上寻求U3D原生GUI的替代方案
A:不美观,OnGUI很耗费时间,使用不方便。

54.请简述如何在不同分辨率下保持UI的一致性
A:NGUI很好地解决了这一点,屏幕分辨率的自适应性,原理就是计算出屏幕的宽高比跟原来的预设的屏幕分辨率求出一个对比值,然后修改摄像机的size。

55.为什么dynamic font在unicode环境下优于static font
A:Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。使用动态字体时,Unity将不会预先生成一个与所有字体的字符纹理。当需要支持亚洲语言或者较大的字体时,若使用征程纹理,则字体的纹理将非常大。

56.Render的作用?描述MeshRender和SkinnedMeshRender的关系与不同
A:Mesh就是指模型的网格,MeshFilter一般适用于获得模型网格的组建,而MeshRender是用于把网格渲染出来的组件。

50.请简述SkinnedMesh的实现原理
A:骨骼蒙皮动画,这种动画中包含骨骼和蒙皮两个部分,蒙皮指将Mesh中的顶点附着在骨骼之上,而且每个顶点可以被多个骨骼所控制,这样在关节的顶点由于同时受到父子骨骼的拉扯而改变位置就消除了裂缝。

51.MeshCollider和其他Collider的一个主要不同点
A:MeshCollider是基于顶点的。建议还使用boxcollider,boxcollider本事是基于算法,没有面的概念。

52.当一个细小的高速物体装向另一个较大的物体时,会出现什么情况?如何避免?
A:穿透力,碰撞检测失败。可以将碰撞体变大,放在FixedUpdate,代码限制。

53.MeshRender中的material和sharedMaterial的区别
A:修改sharedMaterial将改变所有物体使用这个材质的外观,并且也改变储存在工程里的的材质设置。

54.用U3D实现2D游戏,有几种方式?
A:
1.利用引擎自带的GUI和2D系统
2.把摄像机设为Orthographic,用面片作为2d元素
3.利用第三方插件:NGUI、2dToolkit

55.U3D中碰撞器和触发器的区别
A:collider碰撞器会有碰撞的效果,IsTrigger=false,可以调用OnCollisionEnter函数,trigger触发器没有碰撞的效果,IsTrigger=true,可以调用OnTriggerEnter函数。

56.CharacterController和Rigidbody的区别
A:Rigidbody具有完全真实物理的特性,而CharacterController具有一定的物理效果,但不是完全真实的。

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

58.Unity3d提供了几种光源,分别是什么
A:
平行光:Direction Light
聚光灯:Spot Light
点光源:Point Light
区域光源:Area Light(只用于烘焙)

59.U3D下如何安全的在不同工程迁移asset数据
A:
方法1:可以把assets目录和Library目录一起迁移
方法2:导出包
方法3:用unity带的assets server功能

60.动画层(AnimationLayer)的作用是什么
A:动画层作为一个具有层级动画编辑概念的工具,可以用来制作和处理任何类型的动画。

61.Material和PhysicMaterial的区别?
A:PhysicMaterial(物理材质):描述如何处理物体碰撞(摩擦,弹性)。
Material(材质类):为了获得一个对象使用的材质,可以使用Renderer.material属性。

62.什么是导航网格(NavMesh)?
A:一种用于实现自动寻路的网格

63.请简述NGUI中Panel和Anchor作用
A:Anchor包含UIAnchor脚本,UIAnchor的功能是吧对象锚定在屏幕的边缘,或缩放物体使其匹配屏幕的尺寸。
Panel对象有UIPanel脚本,UIPanel是一个容器,它将包含所有UI小部件,并负责将所包含的部件组合优化,以减少绘制命令的调用。

64.Unity摄像机有几种工作方式,分别是什么?
A:透视摄像机和正交摄像机

65.LayerMask.NameToLayer()这个方法有什么用?
A:返回该Layer的编号

66.NGUI与UGUI的优点和缺点
A:
(1)NGUI还保留着图集,需要进行图集的维护。而UGUI没有图集的概念,可以充分利用资源,避免重复资源。
(2)UGUI出现了锚点的概念,更方便屏幕自适应
(3)NGUI支持图文混排
(4)UGUI没有UIWrap来循环scrollview内容
(5)UGUI暂时没有集成Tween组件

67.Unity中Awake和Start谁先执行,Update和FixedUpdate有什么区别?
A:Awake先执行。Update是在每次渲染新的一帧的时候才会调用,FixedUpdate,是在固定的时间间隔执行,不受游戏帧率的影响,FixedUpdate的时间间隔可以在项目设置中更改。

68.Unity如何获得场景中需要加载的数据
A:
Resource.Load
AssetBundle.Load

69.物体发生碰撞时,有几个阶段,分别对应的函数
A:三个阶段,OnCollisionEnter/Stay/Exit函数

70.U3D中几种施加力的方式,请描述出来
A:rigidbody.AddForce/AddForceAtPosition

71.物体自旋转函数
A:transform.Rotate

72.什么是协同程序?
A:在主线程运行时同时开启另一段逻辑处理,来协调当前程序的执行。

73.含义Mathf.Round,Mathf.Clamp,Mathf.Lerp
A:
Mathf.Round 四舍五入
Mathf.Clamp 限制
Mathf.Lerp 插值

74.算法的稳定性指什么?
A:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的。

75.列举稳定的排序算法和不稳定的排序算法
A:
不稳定的排序算法:堆排序,快速排序,希尔排序,直接选择排序
稳定的排序算法:基数排序,冒泡排序,插入排序,归并排序是稳定的排序算法。

76.二分查找
A:
在这里插入图片描述
当数组个数为偶数时,中位值向下取整

77.写一个函数判断单向链表是不是循环链表
A:

78.写一个函数,查询一个数组中的第二大的数,时间复杂度为O(n)
A:

79.把1GB的数据用500Mb的内存空间排序用什么算法?
A:归并排序

80.线程,进程和协程的区别
A:
线程:线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度。
进程:进程拥有自己独立的栈和堆,既不共享堆,也不共享栈,进程由操作系统调度。
协程:协程和线程一样共享堆,不共享栈,协程由程序员在在协程的代码里显示调度。

81.谈谈C#中的内存分配
A:
值类型的分配:虚拟内存中存在一个叫堆栈的区域,我们并不知道它到底在地址空间的什么地方,在一般开发过程中也没有必要知道,我们知道的是值类型就分配于此。值类型在堆栈上分配的时候,是自上而下填充的,也就是从高内存地址开始填充。
比如当前的堆栈指针为100000,这表明它的下一个自由存储空间从99999开始,当我们在C#中声明一个int类型的变量A,因为int类型是四个字节,所以它将分配在99996到99999这个存储单元中。如果我们接着声明double变量B(8字节),该变量将分配在99988到99995这个存储单元。 如果代码运行到他们的作用域之外,这时候A和B两个变量都将被删除,此时的顺序正好相反,先删除变量B,同时堆栈指针会递增8,也就是重新指向到99996这个位置;接下来删除变量A,堆栈指针重新指向10000。如果两个变量是同时声明的。如int A,B,此时我们并不知道A和B的分配顺序,但是编译器会确保他们的删除顺序正好和分配顺序相反。

引用类型的分配:了解堆栈上的分配方式之后,很明显,它的性能相当高,同时我们发现了它的一个缺点:变量的生存期必须嵌套,这对于某些情况是无法接受的,有时候我们你需要存储一些数据并且在方法退出后仍然能保证这部分数据是可用的。为此,虚拟内存另外分配了一部份区域,我们称之为托管堆。托管堆和传统的堆很大的一个不同点在于,托管堆在垃圾收集器的控制下进行工作。引用类就分配在托管堆上,下面我们来看看引用类型的分配过程,
假设我们需要声明一个Person类并对它进行实例化。
Person p=new Person();
首先,系统会在堆栈上给p这个变量在堆栈上分配存储空间,当然它只是一个引用而已,用来存放Person实例在托管堆上的位置,并没有存放真正的Person实例。因为它仅仅是存放一个地址(一个整数值),所以它将在堆栈上占据4个字节的空间。接下来Person实例将会被存放在托管堆上。和堆栈不同,托管堆是由下往上分配的,假设这个实例需要占据10个字节,假设托管堆上的地址为20000,那么它将分配到20000到20009这个存储单元。
需要注意的是,这个分配和实例的大小有关,如果实例小于85000字节,它会被分配在托管堆上。如果超过了85000字节,它将会被分配在LOH(大对象堆)上。这个分配过程比值类型的分配方式更为复杂,因此也就不可避免地有性能方面的损耗。这又是为什么对于小数据量的数据结构我们更愿意使用结构体而不是类。
当然这些是比较单纯的分配方式,实际情况可能比这个复杂。比如Struct里定义一个类实例。该类实例会被分配在托管堆,而它的地址分配在堆栈上。如果类中定义了一个值类型int变量,那么该变量的值会被分配在托管堆上而不是堆栈。

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

83.简述一下对象池,你觉得FPS里哪些东西适合使用对象池
A:对象池就存放需要被反复调用资源的一个空间,当一个对象会大量生成的时候,如果每次都销毁创建会浪费时间,通过对象池把暂时不用的对象放到一个池中(也就是一个集合),当下次要重新生成这个对象的时候先去池中查找一下是否有可用的对象,如果有的话就直接拿出来使用,不需要再创建,如果池中没有可用的对象,才需要重新创建,利用空间换时间来达到游戏的高速运行效果,在FPS游戏中要常被大量复制的对象包括子弹,敌人,粒子等

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

猜你喜欢

转载自blog.csdn.net/qq_37176118/article/details/87085606