RhinoFreak 发表于 2021-4-2 09:58

unity面试题目总结

1.你觉得为什么UI摄像机和场景摄像机能协同工作,而且工作的这么尽如人意呢?
答案:UI摄像机和场景摄像机分别属于两个渲染层(Layer),所以它们之间的渲染互不干扰。它们工作得尽如人意(没有发生先后错乱,UI永远位于场景之上层)的原因就是因为摄像机深度(depth)控制的好。


2.你觉得怎么防止UI控件被点穿(如何过滤掉点击事件)。
答案:使用一个可渲染的物体或者pannel,绑定boxcollider组件即可。如果你单用一个不可渲染的物体(这里点cao一下UIwiget),即使设定了大小和boxcollider,也是无法屏蔽的。(坑在这里)。
//从主这相机到鼠标点发射一条射线
      Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
      //接受射线返回的碰撞信息
      RaycastHit hitInfo;
      //如果射线碰撞到东西
      //EventSystem.current.IsPointerOverGameObject()如果当前鼠标在 ui 上返回true 否则返回false

3.你对UI功能模块之间相互通信有什么好看法。(或者问成Broadcast和sendMes的看法)
(这道题目是我被面的一道题目,相当精髓,后来问我这道题目的人成为了我得同事,多谢他不计较我当时回答的很操蛋,而且现在他仍旧如老师一般帮助我。)
答案:UI模块之间尽量解耦合,使用BroadCast机智或者delegate机智。由于Unity自身的BroadCast和SendMsg效率是很低的,(务必百度一下这俩的区别,都有,我懒得复制粘贴了。)所以推荐使用NGUI自带的那个消息机智。具体的使用方法,下载任何一款NGUI3.5左右的版本,都能清楚的看到。更或者自己实现一个msgerpool也可以,思路是使用泛型写法+字典+delegate,效率也很高。
a.SendMessage      作用:调用一个对象的methodName函数,这个函数可以是公有的也可以是私有的,后面跟一个可选参数(此参数作为传入参数),最后面跟一个可选的设置参数(它有两个选项,后面再讲)。
b.SendMessageUpwards      作用:它的作用和SendMessage类似,只不过它不仅会向当前对象推送一个消息,也会向这个对象的父对象推送这个消息(记住,是会遍历所有父对象)。   
c.BroadcastMessage       作用:这个函数的作用和SendMessageUpwards的作用正好相反,它不是推送消息给父对象,而是推送消息给所有的子对象,当然,也是会遍历所有的子对象。


5.怎样能迅速找到某一个UI控件。
答案:分情况处理,这是一个优化策略的题目。首先如果这个控件我在awake的时候能知道,那么我会把它存成一个private变量,代码中使用的时候直接使用即可。如果不行,这个子物体是动态生成的(他可能有或者没有),那尽量使用FindChild,得到之后加以判断。如果不得不全局找一个东西(比如找到角色物体),才会用Find。
答案是:直接用WorldToScreenPoint方法
public Camera mycamera;//要转化到的目的摄像机,通常canvas在这个摄像机下(即canvas的render mode设置为这个摄像机)
Image kongjian;//自己要获取屏幕坐标的控件,可以是image,也可以是button等等
float x=mycamera.WorldToScreenPoint(kongjian.transform.position).x;
float y=mycamera.WorldToScreenPoint(kongjian.transform.position).y;
//x,y即为控件在屏幕的坐标camera.WorldToScreenPoint()方法返回的是一个position类型 是vector3类型,camera为要转化到的目标摄像机,传入的参数为控件的世界坐标




6.你对遮挡关系有什么好的策略。
答案:这种问题的诞生是由于Ngui2采用了一种zorder+depth方式处理遮挡关系造成的,已经在ngui3里完全屏蔽掉了。只要维护depth即可。
决定Unity渲染关系的层级顺序是: Camera ,sorting layer ,sorting order


7.你对屏幕适配有什么好主意。
答案:屏幕适配根本没有完美的解决方案,如果是全屏模块,那么锁定目标机型,将目标机型做成满屏,其他机型充满宽或高后留白(也叫留黑边)处理即可。如果是屏幕模块(比如战斗界面,主城界面等等,你会看到下边的场景那种),需要采用Anchor来解决。NGUI2 Anchor有独立的控件,NGUI3Anchor已经被搞到Wighet和Pannel中,这个自己下去好好研究研究吧。
      6-1:办法1:调整Canvas的Render Mode属性为Screen Space - Camera:将映射游戏内容的Camera拖入Render Camera中,下一个属性Plane Distance表示UI与Camera的在Z轴距离(其实就是变相反映了UI的Z轴位置)。接着在Canvas Scaler属性里将Ui Scale Mode属性设置为Scale With Screen Size,表示Canvas会根据屏幕比例缩放。下面的Reference Resolution,表示UI宽和高一半的大小。例如设计尺寸为640x960,则x应为640 / 2 = 320,宽应为960 / 2 = 480。下面的Screen Match Mode属性选中Match Width Or Height,表示采用宽度(上文有提到过)或高度(Unity自带适配方式)适配。然后Match调整为0或1,0表示完全宽度适配,1表示完全高度适配,其他值表示介于两者之间采用比例适配
      6-2:办法2:调整Canvas的Render Mode属性为World Space1、将Event Camera设置为映射游戏内容的Camera。2、然后调整Rect Transform组件中的Width和Height为设计尺寸的宽和高,同时将Scale属性的X和Y都调整为0.01(对应unity2d默认情况下像素Pixels与引擎单位Unit对应比例100)。这时,Canvas的宽高正好与摄像机相同。这两种方法都可以将UI调整为与设计尺寸一致,并且在编辑器中运行与真机中运行效果保持一致。


数据逻辑层方面
1.请简述一下你对数据结构的选取有什么看法
答案:批量取,经常遍历的数据,会采取List来存储,经常查找的会采取字典存储。同时如果多个字段比较重要(比如一份配置表经常会id索引以及name索引),我会开辟多个字典进行存储,牺牲空间换取逆向查找效率。
常碰到的几种数据结构:
Array:
数组存储在连续的内存上。数组的内容都是相同类型。数组可以直接通过下标访问。由于是连续存储,所以在两个元素之间插入新的元素就变得不方便。而且就像上面的代码所显示的那样,声明一个新的数组时,必须指定其长度,这就会存在一个潜在的问题,那就是当我们声明的长度过长时,显然会浪费内存,当我们声明长度过短的时候,则面临这溢出的风险。
ArrayList:
   为了解决数组创建时必须指定长度以及只能存放相同类型的缺点而推出的数据结构。ArrayList是System.Collections命名空间下,
ArrayList不是类型安全的。因为把不同的类型都当做Object来做处理,很有可能会在使用ArrayList时发生类型不匹配的情况。数组存储值类型时并未发生装箱,但是ArrayList由于把所有类型都当做了Object,所以不可避免的当插入值类型时会发生装箱操作,在索引取值时会发生拆箱操作需要处理的元素数量确定并且需要使用下标时可以考虑,不过建议使用List
List<T>,
即确保了类型安全。也取消了装箱和拆箱的操作。它融合了Array可以快速访问的优点以及ArrayList长度可以灵活变化的优点。
LinkedList<T>:
   链表在内存存储的排序上是不连续的。这是由于链表是通过上一个元素指向下一个元素来排列的,所以不能通过下标来访问
   1.添加元素和删除元素都要比数组要有优势。
   2.由于其在内存空间中不一定是连续排列,所以访问时候无法利用下标,而是必须从头结点开始,逐次遍历下一个节点直到寻找到目标。所以当需要快速访问对象时,数组无疑更有优势。
Queue<T>:
   先进先出”(FIFO—first in first out)的线性表。Enqueue和Dequeue这两个方法来实现对 Queue<T> 的存取。
Stack<T>:
   后进先出顺序(LIFO)的数据结构时,
使用pop和push来操作。
Dictionary<K,T>:
    以空间换时间,非线程安全Dictionary不能直接序列化,其对象不能出现在检视面板


2.请把这份配置文件解析成你想要的数据结构
   答案:这份配置文件如果是xml或者json,那么它肯定会被先转换成HashTable,然后你根据配置表的可能拥有的字段(比如有一个物体,它有“使用后增加体力”这个字段,有的没有,你要用ContainsKey来检测是否有字段),挨个拆出并且存入你想要的数据结构中,如果你想要的数据结构是字典,需要注意的是在加入key的时候,应该询问是否包含了这个key,如果包含,则修改,如果不包含,则添加,,大家智力都没有问题。。试一试就会很清楚。
如果这个配置文件为excell,那么它将会被转化成一个string数组,数组的每一个元素,都是一个字段数据,按照配置表的顺序挨个取出来存入你得数据结构中即可。
a.C#解析xml文件 : VS中引入XML文件,属性改为始终交新复制,创建xml的投影class类,创建 XmlDocument对象
b.C#解析json文件:引入litjson.dll。//JsonData jsonData = JsonMapper.ToObject(File.ReadAllText("json技能信息.txt"));
c.C#解析excel文件:
string fileName = "装备信息.xls";
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + fileName + ";" + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\"";
//创建连接到数据源的对象 OleDbConnection connection = new OleDbConnection(connectionString); //打开连接 connection.Open();


3.请简述一下C#中,结构体和class的用法
   答案:C#中,结构体属于对象,而类属于引用,结构体不需要new出来,类必须new出来。这是个巨大的坑。比如你搞了一个结构体链表:
List<structA> structtestlist = new List<structA>();
然后给这个链表中注入数据,注入数据之后,你想更改其中的一个链节,你是这么做得
structA structlink = structtestlist;
structlink.data = 3;
这样做,根本没有修改到structtestlist中得值!因为声明structlink那一句话,是个对象,并不是指向那个(链节)的“指针”!
但是如果是class,你这么做毫无烦恼。
这个东西建议大家试试。很坑比。
      何时使用类? 1 内容很多的时候,因为结构总是暗地里拷贝了一个临时变量。 2 需要非常多内存的时候,因为栈的容量有限,而堆通常是足够使用的。 3 需要在声明字段的时候进行初始化。 4 需要从基类继承。 5 需要多态性。接口也可以用来实现多态性,但是因为结构是值类型,尽管它可以从接口继承,但是在多态过程中会进行装箱和解箱的操作。
      在下面的情况下使用结构1 希望能够象原始类型(比如int,double之类的)一样使用它。比如我们可以声明一个复数结构,然后像double类型一样地使用它。 2 需要的内存较少,栈可以完全地容纳它。 3 想避开垃圾收集器的处理,自己掌握资源的释放。 4 只需要缺省的值,而不需要在声明字段的时候赋值。 5 不需要从基类继承,当然,不包括ValueType。 6 不需要多行为


4.接受到网络发来的数据,你会怎么办
   答案:着手做项目之前,会搞一个txt,客户端内部消息协议罗列到上边,这个消息协议是网络协议的处理映射。比如网络协议告诉我,“因为你刚才吃了一个药,吃成功了,现在你得给我刷新,让用户大大能够看到”,我就必须通知所牵连的模块:“你得数据被刷新了,再老地方重新取一次,刷新界面给用户大大看”。牵连到得模块,比如就是战斗UI,它要把血条给加上去,还有character信息的数据基,更改当前血量数据等等。这些模块收到协议之后,改变自己的值:比如UI就会从数据基里取,而数据基会从网络包或者配置表里取等等。


游戏控制流程:
1.你对资源加载有什么看法。
答案:对于比较耗费的加载,属于IO操作,在游戏刚登陆的时候,进行初始化加载。强制加载一些重要模块,比如登陆窗口(用户输入用户名密码的地方)等等。选择性加载一些必要的模块:如果这人需要新手引导,则加载新手引导模块,否则不加载,反之亦然。这些用户一定会用(或者一定不用)的模块,在登陆时候处理好。对于应用模块:比如我打开一个很庞大的UI,这个怎么加载,如果这个模块很吸金,用户用得概率很大,那么必须在登陆时加载,否则那只能用户打开的时候加载了,加载的时候要转圈提示用户。。关于场景加载更加的莫衷一是。既然大家被面到这一步了,相信也不需要我废话了,一个程序有一个程序的活法不是吗?


2.请给我设计一个状态机,完成一个简单的xxxx情景。
a.创建状态机对象。 b.初始化状态机信息和回调函数. c.切换状态通过执行事件实现。d.执行事件的条件判断 . e.执行回调函数
答:状态机并不是单纯的switch结构,如果你是新手,你说switch我可以容忍,如果你干了好些年2Dx,然后想自废武功搞U3d了,再说switch就直接pass了。可以去搜一下相关资料,水不是很深,但篇幅有限。大概意思就是,每个对象都维护自己的状态机,状态机的状态改变,靠状态触发器。所有的状态(不是状态机。。状态机是一个主管它负责调度各种状态,状态是各种。。。状态。。哎不可言传啊。。),都会重写begin,excute,end这三个函数,本来敲了一大堆。。发现说也说不清楚,大家自己去看看吧还是。毕竟这只提供一种面试方式而已。。


3.角色换装,技能释放你会怎么做。
角色换装这个,各有各的活法,尸块换装,纸娃娃贴图等,这个莫衷一是,可以自己百度去,找一个自己喜欢的实现一下试试吧。技能释放水是很深的,这个能答就答,答不上来也不丢人。估计被面这些的,肯定都比我强,也就不需要我比比什么的了。。


4.动态更新有什么看法。
答:这个题牵扯到assetbundle问题。其中assetbundle面对资源的处理方法是截然不同的。比如对于prefab,可以很好的搞上去,对于二进制文件,也能搞得不错,但是对于代码这个东西,往往是大家争论的焦点——毕竟代码这个东西,iosAppStore是肯定不让你搞得,因为unity本身也不受苹果待见,所以它怕被秒杀,也不给用户提供更新脚本的功能。这就导致比如你更新了一个prefab,没法使用它上边挂的脚本!那更新有个jb用。。。提供一下解决代码更新的一点看法,现在我再尝试搞这一块,一孔之见,轻喷
安卓上可以使用unityreflaction机制进行编译后代码的动态更新,这个广大google开发者肯定是知道的。但是问题就是,这种机制会导致很庞大的开发成本——从代码层面完全跟ios搞了个大分支,如果是想跨平台的,这恐怕是不可取的吧。。
第二就是可以采用lua脚本无缝编写方法,因为unity脚本并不是真正的脚本,真正脚本的威力是它可以动态编译到宿主上,这点太牛逼了。lua就是这种牛逼脚本。所以你可以无缝换lua。。。这个没问题。所以立项就应该想好是lua还是什么的。。别回来做了一半,想改lua了,那就sb了。。


所谓闭包,实质就是局部函数(C#、java里多称为方法,包括lambda函数),用到了局部函数外面的变量。其实就是这么个东西。而具体的细节方面就是编译器去做的事了,编译器会根据局部函数及其用到的所有外部变量打包成一个匿名类(局部函数成了匿名类成员方法,外部变量成了匿名类成员变量),然后在原局部函数被调用的时候才建立匿名类对象并通过该对象调用其成员方法(此句一定要理解)。


4.事件委托
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If … Else(Switch)语句,同时使得程序具有更好的可扩展性。使用委托可以将多个方法绑定到同一个委托变量,当调用此变量时(这里用“调用”这个词,是因为此变量代表一个方法),可以依次调用所有绑定的方法


静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作。 将在创建第一个实例或引用任何静态成员之前自动调用静态构造函数。


粘包、分包:
1)TCP为了保证可靠传输,尽量减少额外开销(每次发包都要验证),因此采用了流式传输,面向流的传输,相对
于面向消息的传输,可以减少发送包的数量,从而减少了额外开销。但是,对于数据传输频繁的程序来讲,使用TCP可能会容易粘包。当然,对接收端的程序来讲,如果机器负荷很重,也会在接收缓冲里粘包。这样,就需要接收端额外拆包,增加了工作量。因此,这个特别适合的是数据要求可靠传输,但是不需要太频繁传输的场合(两次操作间隔100ms,具体是由TCP等待发送间隔决定的,取决于内核中的socket的写法)


(2)UDP,由于面向的是消息传输,它把所有接收到的消息都挂接到缓冲区的接受队列中,因此,它对于数据的提取分离就更加方便,但是,它没有粘包机制,因此,当发送数据量较小的时候,就会发生数据包有效载荷较小的情况,也会增加多次发送的系统发送开销(系统调用,写硬件等)和接收开销。因此,应该最好设置一个比较合适的数据包的包长,来进行UDP数据的发送。(UDP最大载荷为1472,因此最好能每次传输接近这个数的数据量,这特别适合于视频,音频等大块数据的发送,同时,通过减少握手来保证流媒体的实时性)参考:https://www.cnblogs.com/kex1n/p/6502002.html


TCP、UDP区别和使用场景
UDP协议(数据包协议)的保护消息边界使得每一个消息都是独立的,在接收端要么接收不到数据要么就是接收一个完整的一段数据.而TCP流传输,却把数据当作一串数据流,他不认为数据是一个一个的消息.
TCP无保护消息边界的解决针对这个问题,一般有3种解决方案:
(1)发送固定长度的消息
(2)把消息的尺寸与消息一块发送
(3)使用特殊标记来区分消息间隔


简述下 MVC 和三层架构的区别
参考:https://www.cnblogs.com/Hackson/p/7055695.html


帧同步、状态同步异同?各自的难点?
帧同步:客户端发送操作给服务端,服务端只转发操作,然后客户端再逐一处理
状态同步:(每个客户端相当于是服务端唯一实例的快照)客户端发送操作给服务端,在服务端进行验证、执行,然后把状态同步给各个客户端


反向动力学 is Kinematic 啥作用?
IK(Inverse Kinematics)即反向动力学,即可以使用场景中的各种物体来控制和影响角色身体部位的运动,一般来说骨骼动画都是传统的从父节点到子节点的带动方式(即正向动力学),而IK则倒过来,由骨骼子节点带动骨骼父节点,具体情况比如人物走路踩到了石头就需要由脚的子节点来带动全身骨骼做出踩到石头的响应。
IK可以使人物和场景更加贴合,从而达到更加真实的游戏效果,如果大家玩过《波斯王子》或《刺客信条》系列,应该对主角的攀爬和飞檐走壁的能力印象深刻,这些都是应用了IK,使动画贴合到具体的场景中进行的表现。参考:https://www.cnblogs.com/hammerc/p/4829943.html
动画系统Layer是干嘛的?
动画融合 https://www.cnblogs.com/hammerc/p/4832637.html


既然已经有了线程为啥还要有协程这个东西?协程的优点?实现原理?
协程, 是个伪线程。 实际运行在主线程。作用是处理异步需求,比如下载、加载、网络请求等耗时操作。相比多线程,优点是不用考虑线程安全问题, 因为就是在主线程,没有共享内存加锁的问题
优势:①协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。②不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多


13.Unity3D是否支持写成多线程程序?如果支持的话需要注意什么?
答:仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用
支持:如果同时你要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine。


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


16.简述四元数的作用,四元数对欧拉角的优点?
答:四元数用于表示旋转
相对欧拉角的优点:
1)能进行增量旋转
2)避免万向锁

3)给定方位的表达方式有两种,互为负(欧拉角有无数种表达方式)


18.矩阵相乘的意义及注意点

用于表示线性变换:旋转、缩放、投影、平移、仿射

注意矩阵的蠕变:误差的积累


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


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


22.Render的作用?描述MeshRender和SkinnedMeshRender的关系与不同
A renderer is what makes an object appear on the screen。
Mesh就是指模型的网格(同名组件是用于调整网格属性的),MeshFilter一般是用于获得模型网格的组件,而MeshRender是用于把网格渲染出来的组件,


23.简述SkinnedMesh的实现原理
http://blog.csdn.net/n5/article/details/3105872


25.Prefab的作用?如何在移动境的设备下恰当地使用它?
答:Prefab在实例化的时候用到,主要用于经常会用到的物体,属性方便修改
http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html


29.MeshCollider和其他Collider的一个主要不同点?
答:Meshcollider再快也是基于V3顶点~~ 建议还是用boxcollider,boxcollider本身是基于算法,没有面的概念。


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


1.请描述游戏动画有哪几种,以及其原理。
主要有关节动画、单一网格模型动画(关键帧动画)、骨骼动画。
关节动画把角色分成若干独立部分,一个部分对应一个网格模型,部分的动画连接成一个整体的动画,角色比较灵活Quake2中使用了这种动画。
单一网络模型动画由一个完整的网格模型构成,在动画序列的关键帧里记录各个顶点的原位置及其改变量,然后插值运算实现动画效果,角色动画较真实。
骨骼动画,广泛应用的动画方式,集成了以上两个方式的优点,骨骼按角色特点组成一定的层次结构,由关节相连,可做相对运动,皮肤作为单一网格蒙在骨骼之外,决定角色的外观。皮肤网格每一个顶点都会受到骨骼的影响,从而实现完美的动画。(骨骼动画是由关节动画发展而来的,如今基本都使用骨骼动画来实现角色动画)


2.alpha blend 工作原理
实际显示颜色 = 前景颜色*Alpha/255 + 背景颜色*(255-Alpha)/255
3.写光照计算中的diffuse的计算公式
实际光照强度 I= 环境光(Iambient) + 漫反射光(Idiffuse) + 镜面高光(Ispecular);
环境光:Iambient= Aintensity* Acolor; (Aintensity表示环境光强度,Acolor表示环境光颜色)
漫反射光:Idiffuse = Dintensity*Dcolor*N.L;
(Dintensity表示漫反射强度,Dcolor表示漫反射光颜色,N为该点的法向量,L为光源向量)
镜面反射光:Ispecular = Sintensity*Scolor*(R.V)^n;
(Sintensity表示镜面光照强度,Scolor表示镜面光颜色,R为光的反射向量,V为观察者向量,n称为镜面光指数)


4.lod是什么,优缺点是什么
LOD技术即Levels of Detail的简称,意为多细节层次。LOD技术指根据物体模型的节点在显示环境中所处的位置和重要度,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。
优点:可根据距离动态地选择渲染不同细节的模型
缺点:加重美工的负担,要准备不同细节的同一模型,同样的会稍微增加游戏的容量。


5.两种阴影判断的方法工作原理
阴影由两部分组成:本影与半影
本影:景物表面上那些没有被光源直接照射的区域(全黑的轮廓分明的区域)
半影:景物表面上那些被某些特定光源直接照射但并非被所有特定光源直接照射的区域(半明半暗区域)
求阴影区域的方法:做两次消隐过程
一次对每个光源进行消隐,求出对于光源而言不可见的区域L;
一次对视点的位置进行消隐,求出对于视点而言可见的面S;
shadow area= L ∩ S
阴影分为两种:自身阴影和投射阴影
自身阴影:因物体自身的遮挡而使光线照射不到它上面的某些可见面
工作原理:利用背面剔除的方法求出,即假设视点在点光源的位置。
投射阴影:因不透明物体遮挡光线使得场景中位于该物体后面的物体或区域受不到光照照射而形成的阴影
工作原理:从光源处向物体的所有可见面投射光线,将这些面投影到场景中得到投影面,再将这些投影面与场景中的其他平面求交得出阴影多边形,保存这些阴影多边形信息,然后再按视点位置对场景进行相应处理得到所要求的视图(利用空间换时间,每次只需依据视点位置进行一次阴影计算即可,省去了一次消隐过程)
若是动态光源此方法就无效了。


5.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几个过程。


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


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


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


19.物理更新一般在哪个系统函数里?
FixedUpdate,每固定帧绘制时执行一次,和update不同的是FixedUpdate是渲染帧执行,如果你的渲染效率低下的时候FixedUpdate调用次数就会跟着下降。FixedUpdate比较适用于物理引擎的计算,因为是跟每帧渲染有关。Update就比较适合做控制。
20.移动相机动作在哪个函数里,为什么在这个函数里。
LateUpdate,,是在所有update结束后才调,比较适合用于命令脚本的执行。官网上例子是摄像机的跟随,都是在所有update操作完才跟进摄像机,不然就有可能出现摄像机已经推进了,但是视角里还未有角色的空帧出现。


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


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


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


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


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


6,NGUI Button怎样接受用户点击并调用函数,具体方法名称是什么
OnClick()
主要是在UICamera脚本中用射线判断点击的物体并通过SendMessage调用OnClick() OnPress()等函数,可以说NGUI的按钮是通过发消息这个方式调用的。


1.AssetBundle.Unload使用时的注意事项?      
答:1.参数为false时,bundle内的序列化数据将被释放,但是任何从这个bundle中实例化的物体都将完好,也不能再从这个bundle中加载更多物体。2.参数为true时,所有从该bundle中加载的物体也将被销毁,如果场景中有物体引用该资源,引用会丢失。         当使用WWW加载bundle完毕后,对其中的资源进行实例化操作的同时不要立即卸载该bundle,因为实例化的过程可能还需要渲染等操作,虽然时间很短,此时若立即进行unload可能会对将要实例化的资源造成影响,以至于没有贴图或者材质等问题。


2.常用的排序算法有哪些?简述各算法的优缺点,使用场景?
答:冒泡排序,简单选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序;


30、当一个细小的高速物体撞向另一个较大的物体时,会出现什么情况?如何避免? 穿透(碰撞检测失败) http://forum.unity3d.com/threads/3353-collision-detection-at-high-speed (碰撞体变大,FixedUpdate, 代码限制)


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


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 )运动 NUGI的代码效率很差,基本上runtime的时候对cpu的贡献和render不相上下
13每帧递归的计算finalalpha改为只有初始化和变动时计算
14去掉法线计算 15不要每帧计算viewsize 和windowsize 16filldrawcall时构建顶点缓存使用array.copy
17.代码剪裁:使用strip level ,使用.net2.0 subset
18.尽量减少smooth group
19.给美术定一个严格的经过科学验证的美术标准,并在U3D里面配以相应的检查工具。


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


概述c#中代理和事件? 代理就是用来定义指向方法的引用。 C#事件本质就是对消息的封装,用作对象之间的通信;发送方叫事件发送器,接收方叫事件接收器


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


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


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


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


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


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


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


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


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


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


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世界中一个点向另一个方向发射的一条无终点的线,在发射轨迹中与其他物体发生碰撞时,它将停止发射。


20.请简述AnimatorController中的Has Exit Time的作用是什么。 当我们勾选了此项,在动画转换时会等待当前动画播放完毕后才会才会转换到下一个动画,如果当前动画时循环动画会等待本次播放完毕转换,所以对需要立即转换动画的情况下一定要取消勾选此项; 还有一种情况时,当前动画播放完毕后会自动转换到箭头所指的下一条状态(没有其它条件时),此时必须勾选此项,否则动画播放完毕后会卡在最后一帧,如果是循环动画,则会一直循环播放。


21.链表和数组的区别 二者都属于同一种数据结构 从逻辑结构上来看: 1.数组申请的是一块连续的内存空间,编译阶段就确定了空间大小,是不允许改变的,不能适应数据动态的增减的情况。当数据增加时,可能会会超出原先定义的数组个数,造成数据越界;当数据减少时,造成资源浪费。 2.链表动态地进行存储分配,现用现申请,可以适应数据动态增减的情况,且可以方便地插入删除数据项。(数组中插入和删除数据项时,需要移动其他的数据项,非常繁琐)链表必须根据next指针找到下个元素 从内存存储上来看: 1.数组从栈中分配空间,对于程序员方便快速,但是自由度小,数组可以根据下标直接存储数据。如果数组中需要增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放入其中。同样的道理,如果想要删除一个元素,需要移动大量的元素去填掉被移动的元素。如果需要快速访问数据,很少或不插入或删除元素,应使用数组。 2.链表从堆中分配空间,自由度大但是申请管理比较麻烦,链表是物理上非连续的内存空间,对于访问数据,需要从头遍历整个链表直到找到要访问的数据,没有数组有效,但是在添加和删除数据方面,只要知道操作位置的指针,很方便实现增删,较数组比较灵活youxiaolv。 从上面可以看出,如果经常访问数组,而很少增加和删除数据,可以用数组;如果经常增加和删除数据,用链表。


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


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


消息传递函数:         
GameObject.SenMessage: 向自身的脚本中发送消息。         
GameObject.BroadcastMessage向自身及物体的脚本发送信息。      
GameObject.SenMessageUpwards: 向自身及父物体中发送消息。


5、UGUI的三层渲染 ① Screen Space-Overlay模式(屏幕控件-覆盖模式) Screen Space-Overlay(屏幕控件-覆盖模式)的画布会填满整个屏幕空间,并将画布下面的所有的UI元素置于屏幕的最上层,或者说画布的画面永远“覆盖”其他普通的3D画面,如果屏幕尺寸被改变,画布将自动改变尺寸来匹配屏幕。 Screen Space-Overlay模式的画布有Pixel Perfect和Sort Layer两个参数: u Pixel Perfect:只有RenderMode为Screen类型时才有的选项。使UI元素像素对应,效果就是边缘清晰不模糊。 u Sort Layer: Sort Layer是UGUI专用的设置,用来指示画布的深度。 ② Screen Space-Camera模式(屏幕空间-摄影机模式) Screen Space-Camera(屏幕空间-摄影机模式)和Screen Space-Overlay模式类似,画布也是填满整个屏幕空间,如果屏幕尺寸改变,画布也会自动改变尺寸来匹配屏幕。所不同的是,在该模式下,画布会被放置到摄影机前方。在这种渲染模式下,画布看起来 绘制在一个与摄影机固定距离的平面上。所有的UI元素都由该摄影机渲染,因此摄影机的设置会影响到UI画面。 Screen Space-Overlay模式的画布多了下面几个参数: u Render Camera:渲染摄像机 u Plane Distance:画布距离摄像机的距离 u Sorting Layer: Sorting Layer是UGUI专用的设置,用来指示画布的深度。 u Order in Layer:在相同的Sort Layer下的画布显示先后顺序。数字越高,显示的优先级也就越高。 ③ World Space(世界控件模式) World Space即世界控件模式。在此模式下,画布被视为与场景中其他普通游戏对象性质相同的类似于一张面片(Plane)的游戏物体。画布的尺寸可以通过RectTransform设置,所有的UI元素可能位于普通3D物体的前面或者后面显示。


1. 可以使用线程在运行时修改纹理吗?   答: 编号纹理和网格物体是存储在GPU内存中的元素的示例,除了主体之外,Unity不允许其他线程对这些类型的数据进行修改。   2. 可以使用线程移动场景上的GameObject吗?   答: 否。在Unity中,获取Transform引用不是线程安全的。


5.你用过哪些插件? 一 界面制作 推荐:NGUI 二 2D游戏制作 推荐:2D Toolkit   // 工具包,工具箱 三 可视化编程 推荐:PlayMaker 四 插值插件 推荐:iTween,HOTween 五 路径搜寻 推荐:Simple Path 六 美术及动画制作 推荐:RageSpline,Smooth Moves 七 画面增强    推荐:Bitmap2Material,Strumpy Shader Editor 八 摄像机管理推荐:Security Camera 九 资源包推荐:Nature Pack 十、造路插件EasyRoads3D


48.请简述四元数的作用以及四元数相对于欧拉角的优点 A.四元数一般定义如下:q=w+xi+yj+zk其中 w,x,y,z是实数。同时,有: i*i=-1    j*j=-1    k*k=-1 B.四元数也可以表示为: q= 有多种方式可表示旋转,如 axis/angle、欧拉角(Euler angles)、矩阵(matrix)、四元组等。 相对于其它方法,四元组有其本身的优点: a.四元数不会有欧拉角存在的 gimbal lock 问题[万向节死锁] b.四元数由4个数组成,旋转矩阵需要9个数 c.两个四元数之间更容易插值 d.四元数、矩阵在多次运算后会积攒误差,需要分别对其做规范化(normalize)和正交化 (orthogonalize),对四元数规范化更容易 e.与旋转矩阵类似,两个四元组相乘可表示两次旋转


50.动画层(Animation Layers)的作用是什么? 动画层作为一个具有层级动画编辑概念的工具,可以用来制作和处理任何类型的动画


52.请说出4种面向对象的设计原则,并分别简述它们的含义。 1) 单一职责原则 (The Single Responsiblity Principle,简称SRP):一个类,最好只做一件事,只有一个引起它的变化. 2) 开放-封闭原则 (The Open-Close Principle,简称OCP):对于扩展是开放的,对于更改是封闭的 3) Liskov 替换原则(The Liskov Substitution Principle,简称LSP):子类必须能够替换其基类 4) 依赖倒置原则(The Dependency Inversion Pricinple,简称DIP):依赖于抽象 5) 接口隔离原则 (The Interface Segregation Principle,简称ISP):使用多个小的专门的接口,而不要使用一个大的总接口。


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


54.法线贴图 、CG动画 A.法线贴图:是在原物体的凹凸表面的每个点上均作法线,通过RGB颜色通道来标记法线的方向,你可以把它理解成与原凹凸表面平行的另一个不同的表面,但实际上它又只是一个光滑的平面。 B.CG动画:原为Computer Graphics的英文缩写。随着以计算机为主要工具进行视觉设计和生产的一系列相关产业的形成,国际上习惯将利用计算机技术进行视觉设计和生产的领域通称为CG。它既包括技术也包括艺术,几乎囊括了当今电脑时代中所有的视觉艺术创作活动,如平面印刷品的设计、网页设计、三维动画、影视特效、多媒体技术、以计算机辅助设计为主的建筑设计及工业造型设计等。


65、itween插件的作用是什么,itween作用于世界坐标还是局部坐标,请列举出3个其常用方法?   iTween是一个动画库,作者创建它的目的就是最小的投入实现最大的产出。让你做开发更轻松,用它可以轻松实现各种动画,晃动,旋转,移动,褪色,上色,控制音频等等“   方法:a、MoveTo物体移动 ;b、ColorTo:随着时间改变对象的颜色组; c、LookTo:随时间旋转物体让其脸部朝向所提供的Vector3或Transform位置


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


68、LayerMask.NameToLayer()这个方法有什么用?   LayerMask的使用是按位操作的,LayerMask.NameToLayer("Players") 返回该Layer的编号。


69、请描述MeshRender中material和shader的区别?   Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出。绘图单元可以依据这个输出来将图像绘制到屏幕上。输入的贴图或者颜色等,加上对应的Shader,以及对Shader的特定的参数设置,将这些内容(Shader及输入参数)打包存储在一起,得到的就是一个Material(材质)   Shader大体上可以分为两类:表面着色器(Surface Shader) 、片段着色器(Fragment Shader)


0、override和overload的区别? 答:override是重写,是重写父类里的函数,而且方法名、返回类型、参数类型和参数个数都要和父类一致; overload是重载,也表示重写父类的函数,但是它只要函数名相同就行,其他的可以不同。


21、Const和ReadOnly的区别? 答:1、const 字段只能在该字段的声明中初始化;而readonly 字段可以在声明或构造函数中初始化。因此,根据所使用的构造函数,readonly 字段可能具有不同的值。 2、const 字段是编译时常数,而 readonly 字段可用于运行时常数。 3、const 字段是编译时常数,而 readonly 字段可用于运行时常数。 4、const 对于引用类型的常数,可能的值只能是 string 和 null,而readonly可以是任何类型。


31、C# List、Hashtable、Dictionary区别? 答:List其实是对数组的封装,当List对象的Item元素数量超过了Capacity的数量时,List对象会重新申请一块大小是原来Capacity的两倍的内存空间,然后将当前所有Item元素以及待添加元素复制到新的内存空间中,因此频繁的添加数据消耗大,但查询速度快;它的内存区域是连续的,可以用角标来取值; Hashtable、Dictionary它们的内存是用key值根据hash算法算出来的,它们的内存区域是不连续的,所以在遍历的时候难免会对内存进行换页操作这样遍历的时间就长; Dictionary:1、类型安全,对值类型没有装箱拆箱操作;2、在单条数据的读取上速度快; 3、数据的存放是有序的 Hashtable:线程安全,适合多线程,无序;


32、unity物理系统的理解? 答:Unity内置了NVIDIA的Physx物理引擎,可以通过物理引擎高效、逼真地模拟刚体碰撞、车辆驾驶、布料、重力等物理效果,使游戏画面更加真实而生动。 33、Unity粒子系统的理解? 答:粒子系统在Unity通常用作制作烟雾,蒸汽,火焰和其他雾化效果,通过一到两个材质和不断绘画,创造一个混乱特效。典型的粒子系统在一个物体上包括一个Particle Emitter粒子发射器, 一个Particle Animator粒子播放器和一个Particle Renderer粒子渲染器,如果想和别的物体交互,可以添加一个ParticleCollider粒子碰撞器到物体上。


41、手机发烫的主要原因? 答:手机CPU是一个高度集成的SOC芯片,它里面不单单集成了CPU中央芯片和GPU图形处理芯片,还有蓝、GPS、射频等一系列关键芯片模块,是智能手机芯片中集成度最高的芯片,模块在高速运作时都会散热出大量热量。通俗的说,手机处理器相当于同时集成了CPU和显卡模块,另外还包含了其他一些模块。熟悉电脑的朋友都知道,CPU和显卡都是发热大户,两者融合在一起,加上又是一个很小的芯片模块,发热量自然是最大的,这样就很好理解了。


42、Render和shader的区别? 答:Shader提供了非常直观、实时的表面基本着色效果,根据硬件的能力,还能显示出纹理贴图、光源影响甚至阴影效果,但这一切都是粗糙的,特别是在没有硬件支持的情况下,它的显示甚至会是无理无序的。Render效果就不同了,它是基于一套完整的程序计算出来的,硬件对它的影响只是一个速度问题,而不会改变渲染的结果,影响结果的是看它是基于什么程序渲染的,比如是光影追踪还是光能传递。


20.StreamingAssets和Resources的功能异同。 答:相同点:都是Unity3d保留的目录。 不同点: 1、Resources里的内容在打包的时候会加密和压缩。而streamingassets里的资源会直接打包,不做处理。 2、Resource里的内容需要用Resources.Load来加载而Streamingassets则需要用www来加载。Assetbundle文件通常也是放在这个文件夹来进行加载。


23.GameObject.Find()和Transform.Find的区别 答;GameObject.Find()是在场景中所有预设中查找。Transform.Find只在子节点中查找。


2.7.Unity3d与android交互的方式是什么 答:u3d调android 采用AndroidJavaClass 和AndroidJavaObject来实现。 Android调Unity3d 采用UnityPlayer.UnitySendMessage(“Main Camera”,”messgae”,edit.getText().toString());


2.8.Unity3d中如何在编辑器中增加一个自定义menu 答: 1、创建c#脚本,引入unityeditor命名空间 2、实现一个静态函数,在函数上加的属性。 3、脚本放在Editor文件夹下。


2.9.Unity3d中shader主要有几种类型 答:表面着色器,顶点片段着色器,固定管线着色器。


2.10.简述Unity3d动画中avator的用处并举例。 答:在动画中有选择性地启用或禁用特定身体部位。比如一个跑的动画和一个开枪动画。如果要实现跑动中设计就需要使用avator。实现上身播放开枪动画,下身播放跑步动画。


2.15.列举减小包体的方法 1. 纹理格式的压缩(重要) 本次减小包体主要改变了纹理的格式:其实是纹理的压缩算法。 主要采用了以下方式减小包体: a.采用RGB Crunched DXT1,RGBA Crunched DXT5的纹理格式,此压缩方式会比RGB Compressed DXT1和RGBA Crunched DXT5小一半还要多 官方未推荐在android平台上使用, 但是在Oppo机型上测试没有问题,其他机型暂时没有测试,采用 RGB Crunched DXT要求图片为2的n次幂 b.去掉纹理格式的mip选项,mipmap会生成多张小图来避免缩小图片时没必要的GPU采样消耗。但使用mipmap的图片会比不使用的图片多占用约三分之一的外存和内存。 2.模型文件的压缩, 模型文件(玩家模型除外)下仅选择了压缩类型为中度,原来工程关闭了模型压缩选项 压缩前mesh占用为 35.4M 压缩后为 中 25.8 M 高 24.7M 现在包体未压缩的模型: 仅玩家模型 4.声音文件的压缩 声音文件主要压缩要点有两个: a.改变声音文件的比特率,原工程采用了声音的Persever选项,现在的声音选择了优化选项 更改前声音 18.5M 更改后 11.7M b.改变声音文件的压缩格式,目前测试采用Vorbis压缩格式声音文件最小 c.暂时没有去查不同文件压缩格式对声音文件的影响(以后补上) 5.场景的压缩(重要,新知识) 场景中静态物体对包体大小的影响 经测试打包时关卡的大小跟场景内静态物体的数量有很大关系,因此当打包时 关卡占用过大时, 减小游戏内静态物体的数量可以减小包体的大小,但是游戏内对静态批处理和Culling等自动化处理都会都是依据static标记进行的, 因此此方法减小包体,会对游戏的帧率有所影响。


协程原理 协程其实就是一个IEnumerator(迭代器),IEnumerator 接口有两个方法 Current 和 MoveNext() ,前面介绍的 TaskManager 就是利用者两个方法对协程进行了管理,只有当MoveNext()返回 true时才可以访问 Current,否则会报错。迭代器方法运行到 yield return 语句时,会返回一个expression表达式并保留当前在代码中的位置。 当下次调用迭代器函数时执行从该位置重新启动。 Unity在每帧做的工作就是:调用 协程(迭代器)MoveNext() 方法,如果返回 true ,就从当前位置继续往下执行。


AssetBundle.Unload(false) 当参数是false时,会释放掉assetbundle里面的关于资源的压缩文件数据,记录着关于该资源的一些数据(应该也保存着该资源的引用) AssetBundle.Unload(false):释放AssetBundle文件内存镜像 AssetBundle.Unload(true):释放AssetBundle文件内存镜像同时销毁所有已经Load的Assets内存对象


资源管理 使用缓冲池 按资源的位置及加载方式分类: 普通资源(Normal) 这类资源存储这工程中Resources目录外, 运行是存储于本地,自动加载。引用方式为直接引用,加载与引用都不需要参数 动态资源(Resources) 这类资源存储与工程中的Resources目录下, 运行时存储于本地,运行时动态加载。Resources.Load 集合资源(Bundle) 以AssetBundle形式存储于本地或网络中。加载时使用WWW方式加载,加载时需要Bundle存放的url路径,版本号等参数。 外部资源(External) 这类资源存储在项目外, 运行时可能存储于本地也可能存储于网络中, 以自定义的方式加载和引用, 加载及引用时所需的参数也需要自己定义。


Character Controller 角色控制器 控制器不会对加在它自身上的力做出反应,也不会自动推开其他刚体。如果想让角色控制器推开其他刚体或者对象,你可以在对象附加的脚本中添加OnControllerColliderHit()函数,这样对它们施加力就能够产生碰撞。 Character Controller相当于刚体碰撞器,但是没有刚体那样的物理特性,照样会触发OnCollision和OnTrigger的函数,照样会有刚体休眠!Character Controller运动时要使用Move或者SimpleMove才会进行相应的检测。


打击感的体现: 1.被击特效:怪物被击中时迸出的火花或者血液,这个不必多解释。如果不同材质的怪物能配合与之对应的被击音效及不同的被击特效,“刀刀入肉”的感觉会非常强。可试着像魔兽3一样将怪物区别为 血肉、木头、金属等几个大类,区别表现。 2.镜头震动:攻击到怪物的一瞬间屏幕会有轻微抖动,暗黑3把这一技巧的价值发挥得淋漓尽致,让这个本来毫无打击感的游戏看起来动感十足。虽然技术实现上没有难度,但实现时须注意抖动的幅度和频率,否则很容易让观众头晕。作者应该是有加轻微的抖动,但幅度比较小,加上镜头一直跟随角色位移,所以震动效果并不明显。另外,不同强度的攻击最好配以不同强度的震动。 3.打击停滞:这一技巧在很多格斗游戏中都有使用,最终怪物猎人将它发扬光大。实现原理也不复杂:武器碰撞到怪物的瞬间,主角的动作会瞬间停滞若干帧,以模拟怪物对武器的“反作用力”。加入这种效果后,在一个攻击动作中打击到多个敌人时,会有“横扫千军”的爽快的体验。当然,这是基于你的打击判定是有真实的“碰撞检测”的情况。在arpg中,即使没有像动作游戏中那种精确碰撞检测,也可以通过一些小手段来模拟这种效果。 4.被击抖动:被打击的怪物会朝受力方向移动,这点类似击退,但是在短时间内它会再弹回到原位,以此模拟怪物本身的“弹性”。这一技巧在拳皇中有出现,尤其是在版边无限连的时候,经常看到对手一直在那里销魂得抖啊抖。 5.击退:楼主已经应用了这个技巧,但我还想补充一些细节。击退是模拟怪物在地上滑行的一个过程。所以如果要让这个过程更加真实,最好不要将它做成一个匀速运动。应该做一个减速然后骤停的过程,来模拟地面“摩擦力”和怪物之间的相互作用,具体物理细节就不讨论了,但想要完美实现,务必同时考虑到“动摩擦”和“静摩擦”的存在。另外,是否击退以及击退距离可做适当随机。远距离的击退还可以加入随机的抛物线,简单的随机能让游戏看起来更加真实。如果在意细节表现,还可以让被击目标在滑行时拖出烟雾特效,效果更佳。 6.对比:在强攻击中(比如连击中的终结move)出现更多更强效果,而其他弱攻击可以适当减弱或者去除一些打击效果(比如击退、震动、停滞)。有对比才有强弱的感觉,再好的打击效果如果一直看也会产生视觉疲劳,偶尔出一下特别强的打击效果反而能震撼到玩家。最佳的表现方式还是要反复体验才能找到的。 7.其他细节: 怪物死了之后也最好也有个击退效果的,而不是原地播死亡动作,而且这个击退距离可能会更夸张,因为怪物已死,不会主动保持平衡了。 击中判定也需要优化,武器没有碰到怪就判为命中,也会影响整体打击感。 作者有做貌似“浮空”的效果,但浮空时怪物最好后仰一定角度并保持被击的pose,同时配合脚下影子才能较好的被玩家辨认出来(战斗场景中怪物的影子被去除了,是考虑到性能问题?)。
页: [1]
查看完整版本: unity面试题目总结