50道常见Unity面试题整理

1、请简述值类型与引用类型的区别

值类型存储在内存栈中,引用类型数据存储在内存堆中,而内存单元中存放的是堆中存放的地址。
值类型存取快,引用类型存取慢。
值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针和引用。
栈的内存是自动释放的,堆内存是.NET中会由GC来自动释放。
值类型继承自System.ValueType,引用类型继承自System.Object。

2、C#中所有引用类型的基类是什么

引用类型的基类是System.Object 。
值类型的基类是System.ValueType。
值类型也隐式继承自System.Object。

3.请简述ArrayList和List<T>的主要区别

List是接口,ArrayList是一个实现了该接口的类,可以被实例化。(这一条应该就是面试想知道的答案)
ArrayList存在不安全类型(ArrayList会把所有插入其中的数据都当做Object来处理);装箱拆箱的操作(费时)

4、请简述GC(垃圾回收)产生的原因,并描述如何避免?

new对象时,当可分配的内存不足GC就会去回收未使用的对象,但是GC的操作是非常复杂的,会占用很多CPU时间,对于移动设备来说频繁的垃圾回收会严重影响性能。下面的建议可以避免GC频繁操作。
减少用new创建对象的次数,在创建对象时会产生内存碎片,这样会造成碎片内存不法使用
使用公用的对象(静态成员,常量),但是不能乱用,因为静态成员和常量的生命周期是整个应用程序。
在拼接大量字符串时StringBuilder。在使用注意,创建StringBuilder对象时要设置StringBuilder的初始大小如:
StringBuilder sbHtml = new StringBuilder (size);
使用object pool(对象池)

5、请描述Interface与抽象类之间的不同

相同点:

都可以被继承
都不能被实例化
都可以包含方法声明
派生类必须实现未实现的方法

区别:

抽象基类可以定义字段、属性、方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。
抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。
抽象类只能被单一继承,接口可以被多重实现。
抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中
抽象类是从一系列相关对象中抽象出来的概念,因此反映的是事物的内部共性;接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性
接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法
接口可以用于支持回调,而继承并不具备这个特点
抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的
如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法

6、下列代码在运行中会产生几个临时对象?

string a = new string("abc"); a = (a.ToUpper() +"123").Substring(0, 2);C#会报错,java可行(个人认为答完这个即可)。
C#中应该是 string b = new string(new char[] {'a','b','c'});产生五个临时变量。

7、下列代码在运行中会发生什么问题?如何避免?

List<int> ls = new List<int>(new int[] { 1,2,3,4,5});
foreach (var item in ls)
{
	Console.WriteLine(item*item);
	ls.Remove(item);
}
//会产生运行时错误,不能一边遍历一边修改。建议使用for循环来代替,foreach建议只用在读取上,不用在修改上。

8、请简述关键字Sealed用在类声明和函数声明时的作用

类声明时可防止其他类继承此类,在方法中声明则可防止派生类重写此方法。

9、请简述private,public,protected,internal的区别

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

10、反射的实现原理?

审查元数据并收集关于它的类型信息的能力。反射个人认为,就是得到程序集中的属性和方法。

实现步骤:

导入using System.Reflection。
Assembly.Load("程序集")加载程序集,返回类型是一个Assembly。
foreach (Type type in assembly.GetTypes()) { string t = type.Name; }

得到程序集中所有类的名称。
Type type = assembly.GetType("程序集.类名");获取当前类的类型。
Activator.CreateInstance(type); 创建此类型实例。
MethodInfo mInfo = type.GetMethod("方法名");获取当前方法。
mInfo.Invoke(null,方法参数)。

11、Unity3D是否支持写成多线程程序?如果支持的话需要注意什么?

仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用
支持:如果同时你要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine。
注意:C#中有lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象。

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

多线程程序同时运行多个线程 ,而在任一指定时刻只有一个协程在运行,并且这个正在运行的协同程序只在必要时才被挂起。
除主线程之外的线程无法访问Unity3D的对象、组件、方法。
在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行。换句话说,开启协程就是开启一个线程。可以用来控制运动、序列以及对象的行为。

13、U3D中用于记录节点空间几何信息的组件名称,及其父类名称?

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

14、简述四元数的作用,四元数对欧拉角的优点?

四元数用于表示旋转。
相对欧拉角的优点:
能进行增量旋转。
避免万向锁。
给定方位的表达方式有两种,互为负(欧拉角有无数种表达方式)。

17.向量的点乘、叉乘以及归一化的意义?

点乘描述了两个向量的相似程度,结果越大两向量越相似,还可表示投影
叉乘得到的向量垂直于原来的两个向量
标准化向量:用在只关系方向,不关心大小的时候

18、在场景中放置多个Camera并同时处于活动状态会发生什么?

实际看到的画面由多个camera的画面组成;由depth、Clear Flag、Culling Mask都会影响最终合成效果。

19、Prefab的作用?如何在移动环境的设备下恰当地使用它?

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

20、如何安全的在不同工程间安全地迁移asset数据?

将Assets目录和Library目录一起迁移。
导出包。
用unity自带的assets Server功能。

21、MeshRender中material和sharedmaterial的区别?

修改sharedMaterial将改变所有物体使用这个材质的外观,并且也改变储存在工程里的材质设置。不推荐修改由sharedMaterial返回的材质。如果你想修改渲染器的材质,使用material替代。

22、请描述游戏动画有哪几种,以及其原理?

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

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

骨骼动画:广泛应用的动画方式,集成了以上两个方式的优点,骨骼按角色特点组成一定的层次结构,由关节相连,可做相对运动,皮肤作为单一网格蒙在骨骼之外,决定角色的外观。皮肤网格每一个顶点都会受到骨骼的影响,从而实现完美的动画。(骨骼动画是由关节动画发展而来的,如今基本都使用骨骼动画来实现角色动画)。

23、alpha blend 工作原理?

实际显示颜色 = 前景颜色*Alpha/255 + 背景颜色*(255-Alpha)/255。

24、lod是什么?优缺点是什么?

LOD技术即Levels of Detail的简称,意为多细节层次。
LOD技术指根据物体模型的节点在显示环境中所处的位置和重要度,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。

优点:可根据距离动态地选择渲染不同细节的模型
缺点:加重美工的负担,要准备不同细节的同一模型,同样的会稍微增加游戏的容量。

25、MipMap是什么?作用?

在三维计算机图形的贴图渲染中有一个常用的技术被称为Mipmapping。为了加快渲染速度和减少图像锯齿,贴图被处理成由一系列被预先计算和优化过的图片组成的文件,这样的贴图被称为 MIP map 或者 mipmap。

26、u3d中碰撞器和触发器的区别?

collider碰撞器会有碰撞的效果,IsTrigger = false,可以调用OnCollisionEnter/Stay/Exit函数。
trigger触发器没有碰撞效果,isTrigger = true,可以调用OnTriggerEnter/stay/exit函数。

27、物体发生碰撞的必要条件?

物体A必须带有(collider+rigidbody)或者CharacterController,另一个物体也必须至少带有collider。

28、什么叫做链条关节?

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

29、物体自旋转使用的函数叫什么?绕某点旋转使用函数叫什么?

transform.Rotate和 transform.RotateAround

30、u3d提供了一个用于保存读取数据的类,(playerPrefs),请列出保存读取整形数据的函数?

PlayerPrefs.SetInt ()与 PlayerPrefs.GetInt()。

31、unity3d提供了几种光源,分别是什么?

平行光:Directional Light;
聚光灯:Spot Light;
点光源:Point Light;
区域光源:Area Light(只用于烘培)

32、unity3d从唤醒到销毁有一段生命周期,请列出系统自己调用的几个重要方法。

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

33、移动相机动作在哪个函数里,为什么在这个函数里。

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

34、什么是渲染管道?

是指在显示器上为了显示出图像而经过的一系列必要操作。 渲染管道中的很多步骤,都要将几何物体从一个坐标系中变换到另一个坐标系中去。
主要步骤有:
本地坐标->视图坐标->背面裁剪->光照->裁剪->投影->视图变换->光栅化。

35、如何优化内存?

压缩自带类库;(只用到一个简单方法就可以自己写而不用using)。
将暂时不用的以后还需要使用的物体隐藏起来而不是直接Destroy掉。
释放AssetBundle占用的资源。
降低模型的片面数,降低模型的骨骼数量,降低贴图的大小。
使用光照贴图,使用多层次细节(LOD),使用着色器(Shader),使用预设(Prefab)。

36、C# 的Lambda表达式怎么写?

表达式形式:(Input Param)=>Expression。在表达式左侧的表示输入参数,右侧的为相应的运算语句或者判断语句等,可包含函数调用等复杂方式。运算符=>读作为goes to,例如下面这个表达t=>t.ClassCode='1001',多做goes to ClassCode equal 1001。
在上述的表达式中,仅仅只有当参数只有一个的时候,括号是可选择的,例如下面这种含有两个参数时候的情况应该是这样子的写法:(a,b)=>a==b
当表达式中的多个参数编译器无法自动判断类型的时候,则需要显式指定类型。
(int firstIndex, string str) => str.IndexOf('Hello') > firstIndex

37、数列1,1,2,3,5,8,13...第n位数是多少?用C#递归算法实现

private void Start()
{
	print(FunTest(4));
}
public int FunTest(int num)
{
	if (num <= 0)
	{
		return 0;
	}
	else if (num == 1 || num == 2)
	{
		return 1;
	}
	else
	{
		return FunTest(num - 1) + FunTest(num - 2);
	}
}

38、unity的mathf?

Mathf.Abs绝对值
计算并返回指定参数 f 绝对值。

Mathf.Acos反余弦
static function Acos (f : float) : float 以弧度为单位计算并返回参数 f 中指定的数字的反余弦值。

Mathf.Clamp01限制0~1
static function Clamp01 (value : float) :float 限制value在0,1之间并返回value。如果value小于0,返回0。如果value大于1,返回1,否则返回value 。

Mathf.Clamp限制
static function Clamp (value : float, min :float, max : float) : float 限制value的值在min和max之间, 如果value小于min,返回min。 如果value大于max,返回max,否则返回value static function Clamp (value : int, min :int, max : int) : int 限制value的值在min和max之间,并返回value。

Mathf.Deg2Rad度转弧度
static var Deg2Rad : float 度到弧度的转化常量。(只读) 这等于(PI * 2) / 360。

Mathf.Mathf.Rad2Deg 弧度转度
static var Rad2Deg : float 弧度到度的转化常量。(只读) 这等于 360 / (PI * 2)。

Mathf.Infinity正无穷
static var Infinity : float 表示正无穷,也就是无穷大,∞ (只读)

Mathf.Lerp插值
static function Lerp (from : float, to :float, t : float) : float 基于浮点数t返回a到b之间的插值,t限制在0~1之间。 当t = 0返回from,当t = 1 返回to。当t = 0.5 返回from和to的平均值。

Mathf.MoveTowards移向
static function MoveTowards (current :float, target : float, maxDelta : float) : float 改变一个当前值向目标值靠近。 这实际上和 Mathf.Lerp相同,而是该函数将确保我们的速度不会超过maxDelta。maxDelta为负值将目标从推离。

Mathf.RoundToInt四舍五入到整数
static function RoundToInt (f : float) :int 返回 f 指定的值四舍五入到最近的整数。 如果数字末尾是.5,因此它是在两个整数中间,不管是偶数或是奇数,将返回偶数。

Mathf.Round四舍五入
static function Round (f : float) : float 返回浮点数 f 进行四舍五入最接近的整数。 如果数字末尾是.5,因此它是在两个整数中间,不管是偶数或是奇数,将返回偶数。

Mathf.Sqrt平方根
static function Sqrt (f : float) : float 计算并返回 f 的平方根。

39、结构体和类有何区别?

结构体是一种值类型,而类是引用类型。
(值类型、引用类型是根据数据存储的角度来分的)就是值类型用于存储数据的值,引用类型用于存储对实际数据的引用。那么结构体就是当成值来使用的,类则通过引用来对实际数据操作。

40、ref参数和out参数是什么?有什么区别?

相同点:ref和out参数的效果一样,都是通过关键字找到定义在主函数里面的变量的内存地址,并通过方法体内的语法改变它的小。

不同点:就是输出参数必须对参数进行初始化。ref必须初始化,out 参数必须在函数里赋值。
ref参数是引用,out参数为输出参数。

41、C#的委托是什么?有何用处?

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

42、Unity中,照相机的Clipping Planes的作用是什么?调整Near、Far两个值时,应该注意什么?

Unity中,照相机的Clipping Planes的作用是什么剪裁平面 。
Near和Far是从相机到开始渲染和停止渲染之间的距离。

43、Heap与Stack有何区别?

heap是堆,stack是栈。
stack的空间由操作系统自动分配和释放,heap的空间是手动申请和释放的,heap常用new关键字来分配。
stack空间有限,heap的空间是很大的自由区。

44、什么是里氏代换元则?

里氏替换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。
通俗点:就是子类对象可以赋值给基类对象,基类对象不能赋值给子类对象。(可以说猪是动物但不能说动物是猪)

45、概述序列化:

序列化简单理解成把对象转换为容易传输的格式的过程。
比如:可以序列化一个对象,然后使用HTTP通过Internet在客户端和服务器端之间传输该对象。

46、堆和栈的区别?

栈通常保存着我们代码执行的步骤,如在代码段1中 AddFive()方法,int pValue变量,int result变量等等。
而堆上存放的则多是对象,数据等。我们可以把栈想象成一个接着一个叠放在一起的盒子。当我们使用的时候,每次从最顶部取走一个盒子。
栈也是如此,当一个方法(或类型)被调用完成的时候,就从栈顶取走,接着下一个。堆则不然,像是一个仓库,储存着我们使用的各种对象等信息,跟栈不同的是他们被调用完毕不会立即被清理掉。

47、客户端与服务器交互方式有几种?

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

48、unity在移动设备上的一些优化资源的方法?

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

49、将图片的TextureType选项分别选为““Texture”和“Sprite”有什么区别?

Sprite作为UI精灵使用,Texture作用模型贴图使用。Sprite需要2的整次幂,打包图片省资源。

50、什么是DrawCall?DrawCall高了又什么影响?如何降低DrawCall?

Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。DrawCall越高对显卡的消耗就越大。
降低DrawCall的方法:
1. Dynamic Batching
2. Static Batching
3. 高级特性Shader降级为统一的低级特性的Shader。
—— 完 ——
相关推荐
评论

立 为 非 似

中 谁 昨 此

宵 风 夜 星

。 露 , 辰

文章点击榜

细 无 轻 自

如 边 似 在

愁 丝 梦 飞

。 雨 , 花