unity3D的面试题

第一部分

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

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

3.请简述ArrayListList<Int>的主要区别

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

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

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

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

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

9.请简述privatepublicprotectedinternal的区别

10.反射的实现原理?

11. .NetMono的关系?

12.简述unity3d支持的作为脚本的语言的名称

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

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

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

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

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

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

19.为何大家都在移动设备上寻求U3D原生GUI的替代方案

20.请简述如何在不同分辨率下保持UI的一致性

21.为什么dynamic fontunicode环境下优于static font

22.Render的作用?描述MeshRenderSkinnedMeshRender的关系与不同

23.简述SkinnedMesh的实现原理

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

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

26.如何销毁一个UnityEngine.Object及其子类

27.为什么Unity3D中会发生在组件上出现数据丢失的情况?

28.如何安全的在不同工程间安全地迁移asset数据?三种方法

29.MeshCollider和其他Collider的一个主要不同点?

30.当一个细小的高速物体撞向另一个较大的物体时,会出现什么情况?如何避免?

31.OnEnableAwakeStart运行时的发生顺序?哪些可能在同一个对象周期中反复的发生?

32.请简述OnBecameVisibleOnBecameInvisible的发生时机,以及这一对回调函数的意义?

33.Unity3D如何获知场景中需要加载的数据?

34.MeshRendermaterialsharedmaterial的区别?

 

第二部分

1.请描述游戏动画有哪几种,以及其原理。

2.alpha blend 工作原理

3.写光照计算中的diffuse的计算公式

4.lod是什么,优缺点是什么

5.两种阴影判断的方法工作原理

6.MipMap是什么?作用?

7.u3d实现2d游戏,有几种方式?

8.u3d中碰撞器和触发器的区别?

9.物体发生碰撞的必要条件

10.CharacterControllerRigidbody的区别

11.物体发生碰撞时,有几个阶段,分别对应的函数

12.u3d中,几种施加力的方式,描述出来。

13.什么叫做链条关节

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

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

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

17.unity3d提供了几种光源,分别是什么

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

19.物理更新一般在哪个系统函数里?

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

21.当游戏中需要频繁创建一个物体对象时,我们需要怎么做来节省内存。

22.一个场景放置多个camera并同时处于活动状态,会发生什么

23.简述prefab的用处和环境

24.如何销毁一个UnityEngine.Object以及其子类

25.为什么u3d会出现组件上数据丢失的情况

26.u3d下如何安全的在不同工程迁移asset数据

 

 

第三部分

1.什么是渲染管道?

2.如何优化内存?

3、动态加载资源的方式?

4、什么是协同程序?

5、你用过哪些插件?

 

第四部分

1.反向旋转动画的方法是什么?

2.碰撞检测需要物体具备什么属性?

3.用代码实现第三角色控制器

4.实现吊机吊物体的功能

5.获取、增加、删除组件的命令分别是什么?

6.Animation.CrossFade命令作用是

7.Application.loadLevel命令为

8.调试记录到控制台的命令是什么?

9.编辑器类存放路径是什么?

10.使用原生GUI创建一个可以拖动的窗口命令是什么?

11.localPositionPosition的使用区别?

12.意义连线

13.写一个计时器工具,从整点开始计时,格式为:00:00:00

14.写出Animation的五个方法

15.怎么拿到一个对象上脚本的方法

16.上机题

17.请简述向量的点乘,向量的叉乘以及向量归一化的几何意义?

 

第五部分

1,在类的构造函数前加上static会报什么错?为什么?
2
C# String类型比stringBuilder类型的优势是什么?
3
C# 函数Func(string a, string b)Lambda表达式怎么写?
4
,数列1,1,2,3,5,8,13...n位数是多少?C#递归算法实现
5
UML图示.

 

 

答案区:

第一部分

1. 请简述值类型与引用类型的区别
答:区别:
1.值类型存储在内存栈中,引用类型数据存储在内存堆中,而内存单元中存放的是堆中存放的地址。
2.值类型存取快,引用类型存取慢。
3.值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针和引用。
4.栈的内存是自动释放的,堆内存是.NET中会由GC来自动释放。
5.值类型继承自System.ValueType,引用类型继承自System.Object。
可参考http://www.cnblogs.com/JimmyZhang/archive/2008/01/31/1059383.html
2.C#中所有引用类型的基类是什么
答:引用类型的基类是System.Object 值类型的基类是System.ValueType
同时,值类型也隐式继承自System.Object
3.请简述ArrayListList<Int>的主要区别
答:ArrayList存在不安全类型‘(ArrayList会把所有插入其中的数据都当做Object来处理)
装箱拆箱的操作(费时)
List是接口,ArrayList是一个实现了该接口的类,可以被实例化。
4.请简述GC(垃圾回收)产生的原因,并描述如何避免?
答:GC回收堆上的内存
避免:1)减少new产生对象的次数
2)使用公用的对象(静态成员)
3)将String换为StringBuilder
5.请描述Interface与抽象类之间的不同
答:抽象类表示该类中可能已经有一些方法的具体定义,但接口就是公公只能定义各个方法的界面 ,不能具体的实现代码在成员方法中。
类是子类用来继承的,当父类已经有实际功能的方法时该方法在子类中可以不必实现,直接引用父类的方法,子类也可以重写该父类的方法。
实现接口的时候必须要实现接口中所有的方法,不能遗漏任何一个。


参考http://www.cnblogs.com/seapub/archive/2012/08/08/2628433.html
6.下列代码在运行中会产生几个临时对象?

 

答:其实在C#中第一行是会出错的(Java中倒是可行)。应该这样初始化:

string b = new string(new char[]{'a','b','c'});
7.下列代码在运行中会发生什么问题?如何避免?

 

答:会产生运行时错误,因为foreach是只读的。不能一边遍历一边修改。
8.请简述关键字Sealed用在类声明和函数声明时的作用
答:类声明时可防止其他类继承此类,在方法中声明则可防止派生类重写此方法。
9.请简述privatepublicprotectedinternal的区别
答:
public:对任何类和成员都公开,无限制访问
private:仅对该类公开
protected:对该类和其派生类公开
internal:只能在包含该类的程序集中访问该类
protected internal:protected + internal
10.反射的实现原理?
答:审查元数据并收集关于它的类型信息的能力。
参考http://blog.163.com/xuanmingzhiyou@yeah/blog/static/1424776762011612115124188/
反射个人认为,就是得到程序集中的属性和方法。
实现步骤:
1,导入using System.Reflection;
2,Assembly.Load("程序集")加载程序集,返回类型是一个Assembly
3, foreach (Type type in assembly.GetTypes())
            {
                string t = type.Name;
            }
   得到程序集中所有类的名称
4,Type type = assembly.GetType("程序集.类名");获取当前类的类型
5,Activator.CreateInstance(type); 创建此类型实例
6,MethodInfo mInfo = type.GetMethod("方法名");获取当前方法
7,mInfo.Invoke(null,方法参数);
11. .NetMono的关系?
答:Mono官网主页
Mono is a software platform designed to allow developers to easily create 
cross platform applications. Sponsored by Xamarin, Mono is an open source 
implementation of Microsoft's .NET Framework based on the ECMA standards for C# and the Common Language Runtime.
mono是.net的一个开源跨平台工具,就类似java虚拟机,java本身不是跨平台语言,但运行在虚拟机上就能够实现了跨平台。.net只能在windows下运行,mono可以实现跨平台跑,
可以运行于linux,Unix,Mac OS等。
12.简述Unity3D支持的作为脚本的语言的名称
答:Unity的脚本语言基于Mono的.Net平台上运行,可以使用.NET库,这也为XML、数据库、正则表达式等问题提供了很好的解决方案。
Unity里的脚本都会经过编译,他们的运行速度也很快。这三种语言实际上的功能和运行速度是一样的,区别主要体现在语言特性上。
JavaScript:和网页中常用的JavaScript不一样,它编译后的运行速度很快,语法方面也会有不少区别。
C#
Boo:可以看做是Python语言的变种,又糅合了Ruby和C#的特性,它是静态类型语言
13.Unity3D是否支持写成多线程程序?如果支持的话需要注意什么?
答:参考http://www.unitymanual.com/3821.html
仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用
支持:如果同时你要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine。
注意:C#中有lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象
14.Unity3D的协程和C#线程之间的区别是什么?
答:http://blog.csdn.net/kongbu0622/article/details/8775037
多线程程序同时运行多个线程 ,而在任一指定时刻只有一个协程在运行,并且这个正在运行的协同程序只在必要时才被挂起。除主线程之外的线程无法访问Unity3D的对象、组件、方法。
Unity3d没有多线程的概念,不过unity也给我们提供了StartCoroutine(协同程序)和LoadLevelAsync(异步加载关卡)后台加载场景的方法。 StartCoroutine为什么叫协同程序呢,所谓协同,就是当你在StartCoroutine的函数体里处理一段代码时,利用yield语句等待执行结果,这期间不影响主程序的继续执行,可以协同工作。而LoadLevelAsync则允许你在后台加载新资源和场景,所以再利用协同,你就可以前台用loading条或动画提示玩家游戏未卡死,同时后台协同处理加载的事宜asynchronous[e ɪˈ s ɪŋ kr ə n ə s] .synchronous同步。 
15.U3D中用于记录节点空间几何信息的组件名称,及其父类名称
答:Transform 父类是 Component
16.简述四元数的作用,四元数对欧拉角的优点?
答:四元数用于表示旋转
相对欧拉角的优点:
1)能进行增量旋转
2)避免万向锁
3)给定方位的表达方式有两种,互为负(欧拉角有无数种表达方式)
17.向量的点乘、叉乘以及归一化的意义?
1)点乘描述了两个向量的相似程度,结果越大两向量越相似,还可表示投影
2)叉乘得到的向量垂直于原来的两个向量
3)标准化向量:用在只关系方向,不关心大小的时候
18.矩阵相乘的意义及注意点
用于表示线性变换:旋转、缩放、投影、平移、仿射
注意矩阵的蠕变:误差的积累
19.为何大家都在移动设备上寻求U3D原生GUI的替代方案
不美观,OnGUI很耗费时间,使用不方便 ,DrawCall
20.请简述如何在不同分辨率下保持UI的一致性
NGUI很好的解决了这一点,屏幕分辨率的自适应性,原理就是计算出屏幕的宽高比跟原来的预设的屏幕分辨率求出一个对比值,然后修改摄像机的size。
原生GUI http://unity3d.9ria.com/?p=2587
NGUI http://blog.csdn.net/mfc11/article/details/17681429
21.为什么dynamic fontunicode环境下优于static font
Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。
使用动态字体时,Unity将不会预先生成一个与所有字体的字符纹理。当需要支持亚洲语言或者较大的字体的时候,若使用正常纹理,则字体的纹理将非常大。
22.Render的作用?描述MeshRenderSkinnedMeshRender的关系与不同
A renderer is what makes an object appear on the screen。

Mesh就是指模型的网格(同名组件是用于调整网格属性的),MeshFilter一般是用于获得模型网格的组件,而MeshRender是用于把网格渲染出来的组件,
23.
简述SkinnedMesh的实现原理

http://blog.csdn.net/n5/article/details/3105872
24.在场景中放置多个Camera并同时处于活动状态会发生什么?
答:游戏界面可以看到很多摄像机的混合
25.Prefab的作用?如何在移动环境的设备下恰当地使用它?
答:Prefab在实例化的时候用到,主要用于经常会用到的物体,属性方便修改
http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html
26.如何销毁一个UnityEngine.Object及其子类
答:Destory
27.为什么Unity3D中会发生在组件上出现数据丢失的情况?
答:组件上绑定的对象被删除了
28.如何安全的在不同工程间安全地迁移asset数据?三种方法
答:

将Assets目录和Library目录一起迁移

导出包

用unity自带的assets Server功能
29.MeshCollider和其他Collider的一个主要不同点?
答:Meshcollider再快也是基于V3顶点~~ 建议还是用boxcollider,boxcollider本身是基于算法,没有面的概念。
30.当一个细小的高速物体撞向另一个较大的物体时,会出现什么情况?如何避免?
穿透(碰撞检测失败)
http://forum.unity3d.com/threads/3353-collision-detection-at-high-speed
(碰撞体变大,FixedUpdate, 代码限制)
31.OnEnableAwakeStart运行时的发生顺序?哪些可能在同一个对象周期中反复的发生?
答:Awake -》OnEnable-》Start
OnEnable在同一周期中可以反复地发生
http://answers.unity3d.com/questions/217941/onenable-awake-start-order.html
32.请简述OnBecameVisibleOnBecameInvisible的发生时机,以及这一对回调函数的意义?
答:当物体是否可见切换之时。可以用于只需要在物体可见时才进行的计算。
33.Unity3D如何获知场景中需要加载的数据?
答:题目是获取的意思?
Resource.Load
AssetBundle
34.MeshRendermaterialsharedmaterial的区别?
修改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。

7.用u3d实现2d游戏,有几种方式?

   1.利用引擎自带的GUI

   2.把摄像机设为Orthographic,用面片作为2d元素

   3.利用第三方插件:NGUI、2dToolkit

8.u3d中碰撞器和触发器的区别?

collider碰撞器会有碰撞的效果,IsTrigger = false,可以调用OnCollisionEnter/Stay/Exit函数

trigger触发器没有碰撞效果,isTrigger = true,可以调用OnTriggerEnter/stay/exit函数

9.物体发生碰撞的必要条件

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

10.CharacterController和Rigidbody的区别

Rigidbody具有完全真实物理的特性,而CharacterController可以说是受限的Rigidbody,具有一定的物理效果但不是完全真实的。

11.物体发生碰撞时,有几个阶段,分别对应的函数

三个阶段,OnCollisionEnter/Stay/Exit函数

12.u3d中,几种施加力的方式,描述出来

rigidbody.AddForce/AddForceAtPosition,都是rigidbody的成员函数

13.什么叫做链条关节

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

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

     transform.Rotate

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

     transform.RotateAround

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

     PlayerPrefs.SetInt 与 PlayerPrefs.GetInt

17.unity3d提供了几种光源,分别是什么

平行光:Directional Light

聚光灯:Spot Light

点光源:Point Light

区域光源:Area Light(只用于烘培)

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

Awake –>OnEnable –> Start  –> Update –> FixedUpdate –> LateUpdate –> OnGUI –> Reset –> OnDisable –> OnDestroy

19.物理更新一般在哪个系统函数里?

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

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

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

21.当游戏中需要频繁创建一个物体对象时,我们需要怎么做来节省内存。

做一个pool,游戏开始时预先实例化足够的数量,然后用的时候取不用的时候收回

22.一个场景放置多个camera并同时处于活动状态,会发生什么

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

23.简述prefab的用处和环境

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

24.如何销毁一个UnityEngine.Object以及其子类

Destroy

25.为什么u3d会出现组件上数据丢失的情况

一般是组件上绑定的物体对象被删除了

26.u3d下如何安全的在不同工程迁移asset数据

方法1,可以把assets目录和Library目录一起迁移,

方法2,导出包

方法3,用unity带的assets server功能

 

 

 

第三部分

 

1.什么是渲染管道?

是指在显示器上为了显示出图像而经过的一系列必要操作。 渲染管道中的很多步骤,都要将几何物体从一个坐标系中变换到另一个坐标系中去。

主要步骤有:

本地坐标->视图坐标->背面裁剪->光照->裁剪->投影->视图变换->光栅化。

2.如何优化内存?

有很多种方式,例如

1.压缩自带类库;

2.将暂时不用的以后还需要使用的物体隐藏起来而不是直接Destroy掉;

3.释放AssetBundle占用的资源;

4.降低模型的片面数,降低模型的骨骼数量,降低贴图的大小;

5.使用光照贴图,使用多层次细节(LOD),使用着色器(Shader),使用预设(Prefab)。

3、动态加载资源的方式?(有时候也问区别,具体请百度)

1.Resources.Load();

2.AssetBundle

4、什么是协同程序?

在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行。换句话说,开启协程就是开启一个线程。可以用来控制运动、序列以及对象的行为。

5、你用过哪些插件?

(最好多熟悉几个插件,问的时候好回答)

 

 

 

第四部分

 

1.反向旋转动画的方法是什么?

2.碰撞检测需要物体具备什么属性?

3.用代码实现第三角色控制器

4.实现吊机吊物体的功能

5.获取、增加、删除组件的命令分别是什么?

获取:GetComponent

增加:AddComponent

删除:Destroy

6.Animation.CrossFade命令作用是:(C)

A.动画放大 B.动画转换 C.动画的淡入为其他动画

7.Application.loadLevel命令为:(A)

A.加载关卡 B.异步加载关卡 C.加载动作

8.调试记录到控制台的命令是什么?

Debug.Log();

9.编辑器类存放路径是什么?

工程目录下的Assets/Editor文件夹下。

10.使用原生GUI创建一个可以拖动的窗口命令是什么?

 GUI.DragWindow();

11.localPosition与Position的使用区别?

localPosition:自身位置,相对于父级的变换的位置。 Position:在世界坐标transform的位置

12.意义连线

Mathf.Round  四舍五入

Mathf.Clamp  限制

Mathf.Lerp   插值

13.写一个计时器工具,从整点开始计时,格式为:00:00:00

14.写出Animation的五个方法

15.怎么拿到一个对象上脚本的方法

GameObject.GetComponent<>();

16.上机题用鼠标实现在场景中拖动物体,用鼠标滚轮实现缩放(用一个Cube即可)。

17.请简述向量的点乘,向量的叉乘以及向量归一化的几何意义?

 点乘的几何意义是:计算两个向量之间的夹角,以及在某一方向上的投影;

叉乘的几何意义是:创建垂直于平面,三角形,或者多边形的向量;参考:http://blog.sina.com.cn/s/blog_9283b6f601017hfw.html

 

 

 

 

 

第五部分

 

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可变,非线程同步。

http://zhidao.baidu.com/question/240364840.html?qbl=relate_question_0&word=String%C0%E0%D0%CD%B1%C8stringBuilder%C0%E0%D0%CD%B5%C4%D3%C5%CA%C6
3,C# 函数Func(string a, string b)用Lambda表达式怎么写?

答:https://msdn.microsoft.com/zh-cn/library/bb397687.aspx
4,数列1,1,2,3,5,8,13...第n位数是多少?用C#递归算法实现

通项公式应该是an = a(n-1) + a(n-2)

a3=2=1+1
a4=3=1+1+1
a5=1+1+1+2
a6=1+1+1+2+3
.........
an=1+1+1+2+3+...+(n-2)+(n-3)
=2+(n-2)(n-3)/2 (n>=3) 
这是通项公式,至于递归?…


5,一个简单的游戏,怪物会走动\攻击\死亡,游戏角色会走动,跳跃\攻击\格挡\死亡,还会接受玩家从输入端输入的指令,NPC会走动,他们彼此之间可以互相通信.请画出以上三种角色的UML图示.

答:
6,NGUI Button怎样接受用户点击并调用函数,具体方法名称是什么

OnClick()

主要是在UICamera脚本中用射线判断点击的物体并通过SendMessage调用OnClick() OnPress()等函数,可以说NGUI的按钮是通过发消息这个方式调用的。
7,怎么判断两个平面是否相交?不能用碰撞体,说出计算方法

答:

https://www.baidu.com/s?wd=怎么判断两个平面是否相交&rsv_spt=1&issp=1&f=3&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=0&rsv_pq=abcac720000083b6&rsv_t=ecdctoXQNURcfX%2FVm8MQdPtiBLttYO4HqJrZ1yNsNcxUqDe6DM4ovlQT4HdHZJMh6guT&inputT=2590&oq=C%23%20lamb&rsv_n=2&bs=c%23%20lambda

8, <愤怒的小鸟>给予初速度以后,怎么让小鸟受到重力和空气阻力的影响而绘制抛物线轨迹,说出具体的计算方法.

 Vector3 v代表初速度v'代表现在的速度,假设小鸟是沿的z轴也就是transform.forward方向运动的质量为1,那么v‘=v-new Vector3(0,g*t,f*t),transform.Translate(v')做的就是抛物线运动(g为重力加速度不要用现实中的需要自己调试,f为阻力也要自己调试设置,t为时间)

 

 

 

 

 

建议:本文以 问题题目  知识点 为重,至于答案的对与错和答案的完整性,自己斟酌哦,当然你有好的答案可以告我哦,谢谢!

 

 

文章整合中参考的网址链接:

http://bbs.9ria.com/thread-288394-1-1.html

http://www.360doc.com/content/13/1225/15/12282510_340022357.shtml

http://game.ceeger.com/forum/read.php?tid=11171&fid=2&page=1

http://tieba.baidu.com/p/2804989828?pid=44186585403&see_lz=1

http://www.taidous.com/thread-2154-1-1.html



http://liweizhaolili.blog.163.com/blog/#m=0&t=1&c=fks_084065083083086067084094083095085080083064084081082071  这是一个超级棒的博客 有空多看看

http://www.jikexueyuan.com/course/1284.html 依据上面视频 补充自己的不足之处

1 知道Http和Tcp的具体区别

2 你必须明白的委托和事件

3 你必须明白的设计模式

4 点乘和叉乘  点乘求的是两个向量之间的投影 叉乘求的是两个向量组成的矩形的面积






本帖最后由 肖红 于 2015-12-18 10:41 编辑 




1,让一个物体围绕某一点旋转,有几种方法?分别是什么?
  • 旋转函数transform.Rotate()来实现。
  • transform的RotateAround(vector3 postion,vector3 axis,float angle)函数
  • [JavaScript] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    5
    varobj1: Transform;
      varobj2: Transform;
      varq:Quaternion;
      q.SetLookRotation(obj1.position, obj2.position);
      transform.rotation=q;

       然后大家拖动obj1和obj2就可以看到物体永远保持z轴朝向obj1,并且以obj2的位置来保持y轴的倾斜度。

2,Mesh,Sphere,Box,Capsule,四种碰撞器。请按照性能开销由小到大进行排序。
collider的性能和效率大概的顺序是:Sphere Collider > Capsule Collider> Box Collider > Mesh Collider. 

3,向量的点积,叉积,在游戏中的应用(分别举一个例子说明)
  • 判断目标在自己的前后方位可以使用下面的方法:
[C#] 纯文本查看 复制代码
?
1
Vector3.Dot(transform.forward, target.position)
返回值为正时,目标在自己的前方,反之在自己的后方
  • 判断目标在机子的左右方位可以使用下面的方法:
[C#] 纯文本查看 复制代码
?
1
Vector3.Cross(transform.forward, target.position).y
返回值为正时,目标在自己的右方,反之在自己的左方
  • a.normalized  和  b.normalized  表示的是两个向量的单位向量, 因为在公式里,有向量和模的除法,得出来的结果就是单位向量,所以我们这里和后面都直接用单位向量来计算,省去不少麻烦。
  • Mathf.Rad2Deg 表示的是 单位弧度的度数。详情请见作者文章:  Unity3D之Mathf.Rad2Deg和Mathf.Deg2Rad
  • 通过叉积计算度数是通过公式 |c|=|a||b|sin<a,b> 来逆向求值。|c| 其实就是叉积的模,换句话说,也代表着 Vector3.Distance (Vector3.zero, Vector3.Cross (a.normalized, b.normalized))的值。

4,输出: 600,0.2,120,119;
该方式对于浮点数会做无条件舍去,失去精确度。  
如果希望获取float的整数部分可以 d = Math.Floor(c);
  • Math.Round:四舍六入五取偶
  • Math.Ceiling:只要有小数都加1
  • Math.Floor:总是舍去小数



5,如何让粒子效果显示在UI前面?(NGUI或UGUI选其一回答)




6,当一个细小的高速物体撞向另一个较大的物体时,会出现什么情况?如何避免?
会发生穿透(碰撞检测失败)
解决方法:
  • 增大细小物体的碰撞体
  • 使用射线检测
  • 可以physics time减小,不建议这样做
  • 确保rigidbody不超过一定的速度,这个也不实用

7,Update(),Awake(),Start()的执行顺序是?游戏开始后,分别在何时执行?
Awake()-> Start()-> Update();
脚本自带函数执行顺序如下:将下面脚本挂在任意物体运行即可得到
Awake ->OnEable-> Start -> FixedUpdate-> Update  -> LateUpdate ->OnGUI ->Reset -> OnDisable ->OnDestroy

  • Awake:用于在游戏开始之前初始化变量或游戏状态。在脚本整个生命周期内它仅被调用一次.Awake在所有对象被初始化之后调用,所以你可以安全的与其他对象对话或用诸如GameObject.FindWithTag()这样的函数搜索它们。每个游戏物体上的Awake以随机的顺序被调用。因此,你应该用Awake来设置脚本间的引用,并用Start来传递信息Awake总是在Start之前被调用。它不能用来执行协同程序。
  • Start:仅在Update函数第一次被调用前调用。Start在behaviour的生命周期中只被调用一次。它和Awake的不同是Start只在脚本实例被启用时调用。你可以按需调整延迟初始化代码。Awake总是在Start之前执行。这允许你协调初始化顺序。在所有脚本实例中,Start函数总是在Awake函数之后调用。
  • Update:正常帧更新,用于更新逻辑。每一帧都执行,处理Rigidbody时,需要用FixedUpdate代替Update。例如:给刚体加一个作用力时,你必须应用作用力在FixedUpdate里的固定帧,而不是Update中的帧。(两者帧长不同)FixedUpdate,每固定帧绘制时执行一次,和update不同的是FixedUpdate是渲染帧执行,如果你的渲染效率低下的时候FixedUpdate调用次数就会跟着下降。FixedUpdate比较适用于物理引擎的计算,因为是跟每帧渲染有关。Update就比较适合做控制。



8,数列 1,1,2,3,5,8,13... 第 n 位数是多少 ? 用 C# 递归算法实现
[C#] 纯文本查看 复制代码
?
1
2
3
4
5
6
Func(n)
{
   if(n==1)return1;
   if(n==2)return1;
   returnFunc(n-1)+Func(n-2);
}



9,当游戏中需要频繁创建一个物体对象时,我们需要怎么做来节省内存?
  • 使用pool对象池。
  • 使用AssetBundle也可以降低一定内存。


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



本帖最后由 辛叙白 于 2015-12-21 14:39 编辑 

1,如何实现磁铁效果?比如酷跑游戏中,获得磁铁道具后,自动吸附附近金币的效果
答:1,可以使用碰撞器实现,在获得磁铁效果后加大player的碰撞器(如果不需要player有跳跃动作可以实现),金币监听player的状态获得               磁铁效果金币加大 碰撞器。金币可以有自己的layer
    2,使用触发器,方法同上不会出现跳跃后没法落地的效果,不过方法能实现确不是很实用。
    3,使用FindGameObjectsWithTag查找金币获得金币的数组,然后通过Vector3.Distance()的方法对距离进行判断在进行销毁。因为获得状态时肯定是有很多
        金币所以要获取的是金币数组。
     4,Unity里有个物理,Physics.OverlapSphere()也可以实现要注意相机的层和深度。
2,Unity中游戏暂停和开始怎么实现?
答:1,Time.timeScale = 0 可以暂停游戏,但这是作用于整个游戏的设置,不单单是当前场景,记得在需要的时候重置回Time.timeScale = 1。
        时间流动速度变为0,但是translate位移动画不能停住,用了第一人称的胶囊体的话镜头依旧能转动,所以所有Transform的移动都应该写在update并跟Time.deltaTime
        相乘的这样才能使速度稳定,这些位置变动便会停掉的。

    2,补充有关于暂停的相关有个帖子还是不错的 http://www.xuanyusong.com/archives/2956
3,Animator Controller中参数类型bool和trigger的区别是什么?分别在何种情况下使用?
答:1,从数据结构看都属于bool类型,trigger在Animator组件中被触发就会自动变为false状态,它只是个触发事件,一旦触发就自动变换数值。
    2,然而bool用于多状态切换比较常用。
4,两个对象发生碰撞的必要条件是什么?
答:主动碰撞双方要有一个Rigidbody存在,并且碰撞双方必须都要有碰撞体组件。
    如果碰撞双方只有一个有刚体,那么那个刚体一定要处于运动的状态下才会有碰撞事件发生。
5,FPS游戏中,哪些东西适合使用对象池技术?
答:对象池就存放需要被反复调用资源的一个空间,比如游戏中要常被大量复制的对象,子弹,敌人,技能特效以及任何频繁重复出现的对象。
6,Lightmapping是什么?为什么要使用?
答:烘培贴图,实时灯光计算十分耗时,随着光源越多会倍增计算耗时。使用Lightmap模拟灯光带来的效果,便不用去计算灯光,会带来性能
    上的大大提升。当然你不用灯光效果也是没问题的,具体还是看项目需求。最简单的直接在3dmas或maya里面烘培完贴图顶点色也行。
7,在塔防游戏中,如何让塔指向进入攻击范围的敌人并射击?请简述程序流程。
答:1,利用画格子的方法把地图分割成等比小格子,
       敌人只负责发送事件,其他的一概不管。每到一个新的格子就发出一个事件比如:GridChange,这个事件通过冒泡到他的上层容器。
       上层容器侦听GridChange事件。一旦侦听到后就通知附近攻击范围内的炮塔。
       炮塔可以设定为几种策略:如果已经有目标则不理会新目标或者永远攻击新目标。
       炮塔攻击目标直到目标走出范围或者死亡。
    2,也可以使用触发器,当敌人进入触发器后播放攻击动画,攻击朝向是被攻击AI的坐标方向。直到出范围或死亡换下一目标。
    3,也可以动画事件,当动画执行到某一帧的情况下添加事件判断敌人是否在攻击范围内,如果在敌人响应被攻击的方法。
8,Unity中,控制3D人物模型位移方式有几种?Animator组件的Apply Root Motion的作用是?
答:1,常用的位移方式有4种组件,如下方法,除了一下方法还有角色控制器移动。
        transform.translate()向某方向移动物体多少距离【默认local坐标系】
        transform.Position()在世界空间坐标transform的位置
        RigidBody.Velocity刚体的速度向量
        RigidBody.AddForce添加一个力到刚体。作为结果刚体将开始移动。
        RigidBody.MovePosition移动刚体到position
        NavMeshAgent组件的SetDestination函数,设置自动Path目标点
        CharacterController组件的Move函数,每次都绝对运动
        Vector3.MoveToward 当前的地点移向目标
    2,如果我们勾选了Animator组件中的Apply Root Motion选项,角色的Transform将不能通过脚本来直接赋值,而是通过动画的运动的来改变的
       如果我们不勾选我们就可以用脚本改变角色的Tranform
9,Unity中如何实现序列帧动画?
答:1,Window→Animation组件。切割好的帧图片直接拖入Unity,Hierarchy中自动生成帧动画
    2,也可以通过程序来实现,例如以每帧一个图形文件来控制。以下是复制百度的JS代码
    
[JavaScript] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
vartimeElasped : float = 0;
varcurFrame : int = 0;
varfps : float = 10;
varani : Texture2D[];
functionUpdate () {
timeElasped += Time.deltaTime;
if(timeElasped >= 1.0 / fps)
{
timeElasped = 0;
    curFrame ++;
if(curFrame >= ani.length)
{
curFrame = 0;
}
    guiTexture.texture = ani[curFrame];
}
}

10,对象包含Box Collider 2D组件,且作为trigger使用时,检测是否有对象进入的函数是?
答:OnTriggerEnter2D() 例如有个play位移拾取金币,金币对象就要加上刚体,Box Collider 2D组件,当play进入金币时,销毁积分加属性等。
[C#] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
8
9
voidOnTriggerEnter2D (Collider2D collision)
   {
       if(collision.tag=="Sqian")
       {
           Destroy(collision.gameObject);
           Score += 10;
           UpdateScore();
       }
   }


PS:强迫症排版累成死狗



本帖最后由 辛叙白 于 2016-1-5 19:04 编辑 

1,如何避免点击UI按钮时穿透,同时触发了相同位置场景模型的点击事件的情况?(NGUI 判断 是否点击到UI

答:1,通过射线分层处理,显示层分为不同的Layer,用UICamera发射一条射线并脚本里设置他的响应事件的层。
    2,在高版本的NGUI中,UICamera中有一个变量isOverUI,这个值为真时表示点击到了UI,反之就是没有。
2,切换场景时,如何让背景音乐持续播放,而不是重新播放?
答:1,使用DontDestroyOnLoad()方法挂载一个音乐组件,当然这个方法也可以保存一些全局游戏脚本。
        但是使用时避免重复调用,可以用判断的方式来调用或者销毁但是不是很好,最好的方式是写个
        静态全局的单例类,在游戏初首次进入时绑定这个脚本,这样这个方法永远只会走一遍。
[C#] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
publicstaticGlobal instance;
  
        staticGlobal()
        {
                GameObject go = newGameObject("Globa");
                DontDestroyOnLoad(go);
                instance = go.AddComponent<Global>();
        }
  
        publicvoidDoSomeThings()
        {
                Debug.Log("DoSomeThings");
        }
  
        voidStart ()
        {
                Debug.Log("Start");
        }

3,如何实现游戏存档和读档的功能?
答:1,Unity提供了一个用于本地持久化保存与读取的类——PlayerPrefs。工作原理非常简单,以键值对
        的形式将数据保存在文件中,然后程序可以根据这个名称取出上次保存的数值。
        PlayerPrefs类支持3中数据类型的保存和读取,浮点型,整形,和字符串型。
        分别对应的函数为:
这些函数的用法基本一致使用Set进行保存,使用Get进行读取
        SetInt();保存整型数据;
        GetInt();读取整形数据;
        SetFloat();保存浮点型数据;
        GetFlost();读取浮点型数据;
        SetString();保存字符串型数据;
        GetString();读取字符串型数据;
     2,XML,sql,txt等配置文件都可以实现存读等功能,PlayerPrefs自带的类只能实现简单的存取功能。

        XML存档参考http://blog.sina.com.cn/s/blog_471132920101d3kh.html。
4,什么是协同程序?请举一个游戏中应用协程的例子。

答:Unity的协程系统是基于C#的一个简单而强大的接口 ,IEnumerator,它允许你为自己的集合类型编写枚举器。

    1,所谓协同,就是在主程序运行的时间同时开启另外一段逻辑处理,来协同当前程序的执行,
       当你在StartCoroutine的函数体里处理一段代码时,利用yield语句等待执行结果,这期间不影响主程
       序的继续执行,可以协同工作。
    2,在游戏中游戏开始前的倒计时就可以用到协同程序,网络游戏的加载进度,游戏中的顺序控制等。
       下面举个计时的例子,方法的状态被存储了,这使得方法中定义的这些变量都会保存它们的值,即使是在不同的帧中
[C#] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
IEnumerator CountSeconds() 
    intseconds = 0; 
     
    while(true
    
        for(floattimer = 0; timer < 1; timer += Time.deltaTime) 
            Yieldreturn0; 
     
        seconds++; 
        Debug.Log(seconds +" seconds have passed since the Coroutine started."); 
    
}
    
5,什么是游戏框架?使用框架的好处是什么?
答:1,游戏框架是比较上层的封装,是一套快速搭建游戏的代码结构。
    2,使用游戏框架开发能节约工程时间,易维护,易扩展,易阅读开发,可复用。
       选择框架和使用框架是控制框架的基础。
6,如何在Unity中播放视频?

答:1,首先下载安装Quicktime ,U3D承认的视格式为.mov, .mpg, .mpeg, .mp4, .avi, .asf格式。
    2,创建一个对象,使用对象拖拽的形式为Mov Texture对象赋值,之后就可以在脚本中使用它了。
[C#] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
publicclassTest: MonoBehaviour
{
  
        //电影纹理
        publicMovieTexture movTexture;
  
        voidStart()
        {
                //设置当前对象的主纹理为电影纹理
                renderer.material.mainTexture = movTexture;
                //设置电影纹理播放模式为循环
                movTexture.loop = true;
        }
  
        voidOnGUI()
        {
                if(GUILayout.Button("播放/继续"))
                {
                        //播放/继续播放视频
                        if(!movTexture.isPlaying)
                        {
                                movTexture.Play();
                        }
  
                }
  
                if(GUILayout.Button("暂停播放"))
                {
                        //暂停播放
                        movTexture.Pause();
                }
  
                if(GUILayout.Button("停止播放"))
                {
                        //停止播放
                        movTexture.Stop();
                }
        }
}

       3,另一种是看MOMO帖子学来的,用GUI的方式,直接调用DrawTexture()。程序参考MOMO帖子
       http://www.xuanyusong.com/archives/1019
7,跑酷游戏的无尽关卡是如何生成的?
答:设计多种场景块,加载到对象池,对象缓存复用,根据游戏内容制定随即组合的规则,然后根据规则
    调用不同的场景块。例如有的场景是特定场景。用量化的方法定义难度。
8,如何增强ARPG游戏的打击感?
答:1,从美术资源上看,不管是2D还是3D角色的动作流畅度跟动画的合理性都能提高游戏的打击感。
    2,游戏中角色的技能或者特定动作加上拖尾效果,多一些技能特效,画面扭曲效果。被打击方的状态控制。
    3,相机,也就是主视角可以增加震动效果,镜头的一些特效,例如主角的健康状态显示等。
    4,音效的增加,音效是非常非常重要的一个选项。
    5,设备上的体现,理由手机或者游戏手柄的震动。
9,游戏慢镜头回放功能的实现思路?如足球游戏中的精彩镜头回放。
答:1,直接录屏将整个动画保存出mp4格式进行压缩,如果是PC端的话找一些录屏插件,移动端也有插件不过好像
       都不支持视频保存,记录回放插件EzReplayManager,EveryPlay等移动端插件都比较好用
    2,状态记录同步,记录每一帧所有角色状态,包括位置,旋转等,这种方式代码比较容易实现,
       文件量会比较大,3分钟视频,一秒钟30帧,需要36030 = 5400帧如果每个角色每一帧都进行
       记录至少要3M以上,如果角色少做一些简单的优化比如,只有发生修改的时候才记录会明显的
       降低文件量,但是对于移动端流量还是很有压力。
10,LOD技术是什么?优缺点是?
答:1,LOD是Levels of Detail的简称,译为多细节层次。LOD技术指根据物体模型的节点在显示环境中所处的位置
       和重要度,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。
       一个有关于LOD的插件Mesh Baker LOD 1.4
    2,LOD的优点可以根据距离动态地选折渲染不同细节的模型
    3,LOD缺点增加游戏容量不同细节的模型要准备多个,同时增加美术的工作量

2016年到了,你的新年愿望/计划是什么?


答:新的一年,新的选择,愿望就是让我的新方向能够顺利的进行下去。
       新的一年,新的选择,放弃了5年的工作经验从一个新的行业新的岗位新的层次从新出发从心出发。
       新年计划,就是工作学习积累。据说每个程序员都要标配一个美术妹纸。妹纸你在哪。




本帖最后由 天之道 于 2016-1-25 00:49 编辑 

 左手,一个第四期问答嘉宾,
右手,一个第五期问答老师,  

不好意思,DC老湿横屏了
 


没错,由于上一期做的反响还不错,
所以,
这一期,他们还是继续盛情邀请了本人。

那么让我们马上进入正题吧~




原题1、什么是单例?举一个游戏中使用单列的例子。

答:单例,啊~那是一种内功心法~~
而且是行走江湖必备的一种最基本的内功心法。
说到单例,我们得要把后面两个字补全,也就是单例模式
单例模式是传说中的23种设计模式之一。

为什么DC老湿说其实内功心法呢,
我们来做横向比喻

游戏引擎是兵器、编程语言是外功、设计模式是内功
只会设计模式不会引擎不会编码的话,就像天龙八部里的虚竹,空有一身从无崖子那边继承过来的90年的内功,在成为逍遥派掌门之前,却无任何用武之地(用现在的话讲,叫做然并卵)
只会编程语言,其他两个都不会或者只会一点皮毛的话,那一辈子永远只是个小角色,永远只能写些小功能,处理不了大系统,或者说是一种高不成低不就的存在,如灌篮高手里木暮
只会引擎,其他两个都不会的话,可能比较的偏向美术、场景布局等,当然高级点的可以是建模师、动画师(3dsmax、maya)、特效师(ae、unity)


官方解释:
单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。


如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
在游戏中使用单例的例子
比如音乐管理类,游戏主页的背景音乐、战斗界面的背景音乐、技能音效、UI控件触发音效等等,这些是不是把他们放在统一的一个类里面去管理,效率更高,然后别的系统模块需要什么音乐音效,直接调音乐管理类就好了。


和单身汪不一样,一个办公室里面单身汪可以有很多只  

但是一个游戏开发目里面,且只有一个音乐管理类  

名字随便起,可以叫也可叫MusicController,等等


显然归纳起来单例模式的要点有三个;
一是某各类只能有一个实例;
二是它必须自行创建这个事例;
三是它必须自行向整个系统提供这个实例。


一般c#实现单例
[C#] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
publicclass AudioManager
{
    privatestatic AudioManager instance;
    publicstatic AudioManager Instance
    {
        get
        {
            if(instance == null)
                instance = newAudioManager();
 
            returninstance;
        }
    }
}

注意:unity3D的编程方式就是组件化编程,如果脚本继承自MonoBehaviour,对其new的话会报警告
 
那么有人问:老湿,我在Unity里的某个类是继承自Monobehaviour的,非要让其实现单例,该怎么弄得
DC老湿:你可以在Awake()方法里面,写上Instance = this;
注意,这个Instance是要在方法外部定义好 public static XXX Instance; 
XXX是类名





原题2、Unity实现昼夜交替的方法或思路?

答:最最简单的做法,就是两个相机挂天空盒子的做法,通过一个Toggle开关来切换白昼和黑夜。
如图

由于材质球的关系,gif图里的黑夜不是特别的明显。

[C#] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
usingUnityEngine;
usingUnityEngine.UI;
usingSystem.Collections;
 
publicclass DayOrNight : MonoBehaviour {
 
    publicToggle mToggle;
    publicCamera DayCamera;
    publicCamera NightCamera;
 
    voidStart ()
    {
        if(mToggle != null)
        {
            //isTag(mToggle.isOn);
            mToggle.onValueChanged.AddListener(isTag);
        }
      }
 
    privatevoid isTag(boolon)
    {
        DayCamera.enabled = on;
        NightCamera.enabled = !on;
    }
}
这种做法实在过于简单粗暴,可以说是简单的极致
我们来看一个复杂做法的极致

知乎上碰巧最近有一篇文章刚好讨论了这个问题
http://www.zhihu.com/question/39560196

我看到有人说用Time of Day插件
下面是两张gif的动态图,加载会比较慢,不过绝对值得你等待一看。
如图

昼夜交替.gif (9.96 MB, 下载次数: 0)

下载附件  保存到相册

2016-1-22 03:46 上传

这一张是月亮与太阳刚好对立位置,也就是正午12点太阳在正上方,午夜24点月亮在正上方


这一张,大家注意在其检视面板里的我鼠标示意的下方Position选项,选了一个Realistic,也就是逼真
也就是晚上19点到20点的某个时间点,月亮是处于正上方的。

这个Position的选项让我非常好奇,想一探究竟,看看其代码是如何实现的。
代码非常的彪悍啊,完全看不懂这些个参数代表什么,不过妙在注解是超链接,点过去一看


我去,看上去非常高深的样子,标题是如何计算行星的位置
Paul SchlyterStockholmSweden该网页作者的信息
保罗斯里特,斯德哥尔摩天文台,瑞典


哦,原来这些个N、i、w。。。原来是天体行星的轨道参数

这是太阳和月亮的轨道参数,
哦,插件的作者在Unity的Asset Store上叫Mod Monkeys,
一个来自德国某个工作室的独立游戏开发者,
参考了瑞典首都斯德哥尔摩天文观测台的保罗斯里特的天体行星轨道计算
硬是把这些高深的天文学原理,用c#脚本翻译,并借助Unity实现出想要的功能,
6666
我想这个位独立开发者一定是为天文爱好者


说了这么多,截了这么多图,也装了这么多腔(bi)。也无非就是和大伙介绍介绍人家老外做的插件。至少比我那粗暴的强行交换相机换天空盒要高大上多了。

一开始看到在Asset Store上卖60刀,以为就几个漂亮的天空盒,加点shader就卖这么贵,一定是疯了。细看才知道原来被后应用着天文学。

而且其文档清晰详细  ,从实现原理,到代码详解都有,还算是个比较良心的插件作者。
有时间研究研究,一定会获益颇多的。

我把这个插件分享给大家~
 Time of Day - Dynamic Sky Dome.zip (4.2 MB, 下载次数: 134) 

另外一些别的做法,知乎上面也有讲到什么通过旋转平型光,
或是smooth平滑改变环境光亮度
亦或是自己写shader,实现光影反射等绚丽效果
由于篇幅的原因这里也就不多啰嗦了。


及时反馈【1】:网名“贼子哪里走”同学问的兼容性的问题,是的,我本人使用u4.x版本导入的该插件,没问题。由于u5.x改了很多的API,而Time of Day这个插件我是在某牛上下的,还只是2.3.1版本,这个版本确实不支持u5.x
这样,我上网再找找,最新版的Time of Day应该是能支持u5.x的
 
及时反馈【1-1】
经过一番搜索,不负众望,我还是算比较容易的在网上找到了Time of Day 插件3.0版,
 ,这个版本u5.x就可以用了
下面分享给大家,这个插件的作者确实非常良心,文档说明、版本号都相当清晰明了~
 Time of Day Dynamic Sky Dome 3.0.rar (7.48 MB, 下载次数: 61) 




原题3、塔防游戏中(保卫萝卜),底图的路劲信息如何存储?让怪物沿着路劲走的方法是?

答:博客园的这篇文章http://www.cnblogs.com/hll2008/p/4235714.html
写的还是非常详细的,项目虽然是cocos2d - x3.x
但是思路都是一样。
如图  

底图路进店信息如何存储,一张图一个ID,然后把路径点信息保存到xml文件里加在图的,根据id去xml取路径点信息,就ok了。
至于让怪沿着路径点走的方法,就是坐标点减坐标点得到其位移向量。再给其一个速度,再用距离判断是否开始计算移动到下个点。

至于向量计算,我给个网址分享给大家http://blog.gamerisker.com/archives/347.html,这里描述的相当详细。





原题4、《英雄联盟》中,带位移的技能能否穿越墙壁如何来判定?如闪现过墙/撞墙(以程序角度)

答:真把我当无所不会吗?
先说如果这个在客户端来判断的话,可以用触发器,如图  ,这个是Unity官方例子Angrybots的编辑器界面,你能清楚的看到触发器的范围,然后你可以通过触发器来判断实现是否穿墙还是撞墙。详细链接地址。触发器实现的代码就不用我多说了吧,网上搜搜都有的。

但是LOL毕竟是个强联网的MOBA游戏,
首先申明我没有参与制作过moba类游戏,所以以下的观点,也只是我个人粗浅的看法而已。如有说的不对的地方,还望不吝赐教
强联网的MOBA游戏,其实你的鼠标每点一下都是在跟服务器交互信息,服务器判断你是否可以进行接下来的操作,然后把数据返回客户端,再呈现在我们玩家眼前的,由于过程可能也就几百毫秒,所以在网络情况好的前提下,是感觉不出来。
否则主要逻辑全在客户端的话,那就外挂满天飞了,什么一键五杀,1v9,出门装就无尽之刃什么的妥妥的有。
那如果在服务端做判断、做验证的话,服务端肯定应该有存储整张地图信息,并随着游戏的发展实时更新地图信息,包括英雄当前所在位置信息,
通过地图信息和英雄位置信息,这两点可以计算出英雄离墙的距离。
进而通过距离(Unity的c#封装的代码Vecter3.Distance(英雄位置,墙体位置),服务端的选择的语言以及封装的代码那就有各式各样了)、
当前鼠标位置(屏幕坐标到世界坐标的转换)、
墙体薄厚(tag标识)
这三条来判断是可以穿墙还是撞墙。





5、继承和接口的用法和区别?

答:这个问题的表述就是一个门外汉的表述,应该这么问:
类的继承与接口的继承,各自的用法和区别
(或者像网上说的,实现接口和类继承的区别)

这样问才明了。

为什么这么说呢,因为这两个从表面形式上看上去差不多,都是在类名后面冒号然后是基类或者接口
虽然看上去相似,但二者的区别可大不一样

接口定义了一份契约,实现了接口的类或结构就意味着遵守接口定义的契约,
接口只允许包含方法、属性、索引器和时间的签名,只允许包含签名;
不允许包含实现接口,不含常量、字段、运算符、实例构造函数、析构造函数、以及任何静态成员。

标志:接口,interface  IA { ...}(一般接口命名虽然没有强制要求,但是大家约定俗成一般都会在前面加个I) ,class B: IA(然后这个B要实现IA里面定义的方法)
接口的继承:如果你觉得契约还是印象不深刻,那你可以把其想象成卖身契。

标志:类, class A{ ...}
classB: A
类的继承:B继承了A之后呢,就可以直接调用A里的公共属性或者方法,还可以重写A(父类)里的虚方法等。

注意一点:c#只能继承一个类,但可以继承多个接口





6、如何控制子弹发射频率,技能冷却时间(需示代码)

答:那我就用DFGUI,做个栗子吧~
又是gif图,请耐心等待加载
如图

条件简陋,就用背包图代替子弹发射器,用蓝色箭头代替子弹
然后底下的技能图,我是直接拿的DFGUI的第一个官方的例子里的部分预设拷贝过来的。

EmissionManager发射器管理类,其实干的事情呢,就是先获取全部技能槽信息,然后技能槽绑定点击事件
点击事件里的判断什么时候可以去实例化子弹并发射,什么时候是做cd冷却时间的表现等。
[C#] 纯文本查看 复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
usingUnityEngine;
usingSystem.Collections;
 
publicclass EmissionManager : MonoBehaviour {
 
    publicdfSprite ArrowTemp;
    publicSpellSlot[] slots;
 
    //之所public出来是方便我在检视面板查看信息的,正常来说应该是private
    publicint CrtClickIndex = 0;
 
        voidStart ()
    {
        if(ArrowTemp != null)
        {
            ArrowTemp.IsVisible = false;
        }
 
        for(inti = 0; i < slots.Length; i++)
        {
            slots[i].GetComponent<dfControl>().Click += OnClickSpell;
        }
        }
 
    //技能槽点击事件
    voidOnClickSpell(dfControl control, dfMouseEventArgs args)
    {
        if(!args.Used)
        {
            var slot = control.GetComponent<SpellSlot>();
            if(slot.Spell != string.Empty)
            {
                if(slot.IsSpellActive)
                    return;
 
                #region 有bug,当不停点击多个技能槽的时候,冷却时间就混乱了,~( TロT)σ 可能当时作者写该算法的时候没有考虑那么多
                //var spell = SpellDefinition.FindByName(slot.Spell);
                //slot.onSpellActivated(spell);
                #endregion
 
                #region 所以就只好自己实现咯 ╮(╯▽╰)╭
                var cdSprite = control.Find("CoolDown")asdfSprite;
 
                dfTweenFloat cdTween = slot.GetComponent<dfTweenFloat>();
                if(cdTween == null)
                {
                    //纯粹只是为了区别不同技能槽的cd时间,正规项目还是统一读配表的
                    var timeLenght = slot.SlotNumber * 0.2f;
 
                    cdTween = addCDTween(cdSprite.gameObject, timeLenght);
                    cdTween.TweenCompleted -= cdTweenCompleted;
                    cdTween.TweenCompleted += cdTweenCompleted;
                }
 
                //不同的技能槽,且不在技能冷却时间
                if(CrtClickIndex != slot.SlotNumber && !slot.IsSpellActive)
                {
                    //记录当前点中第几个技能槽的信息
                    CrtClickIndex = slot.SlotNumber;
 
                    slot.IsSpellActive = true;
                    cdSprite.IsVisible = true;
 
                    cdTween.Reset();   //重置补间动画
                    cdTween.Play();    //走你(播动画)
 
                    var ArrowObj = Instantiate(ArrowTemp.gameObject, ArrowTemp.transform.position, Quaternion.identity)asGameObject;
                    ArrowObj.GetComponent<dfControl>().IsVisible = true;
                    ArrowObj.transform.parent = this.transform;
                    var am = ArrowObj.GetComponent<ArrowMove>();
                    am.IsMove = true;
                }
                //相同的技能槽,且不在技能冷却时间
                elseif (CrtClickIndex == slot.SlotNumber && !slot.IsSpellActive)
                {
                    slot.IsSpellActive = true;
                    cdSprite.IsVisible = true;
 
                    cdTween.Reset();   //重置补间动画
                    cdTween.Play();    //走你(播动画)
 
                    var ArrowObj = Instantiate(ArrowTemp.gameObject, ArrowTemp.transform.position, Quaternion.identity)asGameObject;
                    ArrowObj.GetComponent<dfControl>().IsVisible = true;
                    ArrowObj.transform.parent = this.transform;
                    var am = ArrowObj.GetComponent<ArrowMove>();
                    am.IsMove = true;
                }
              
                #endregion
            }
            args.Use();       
        }
    }
 
    /// <summary>
    /// 补间动画事件监听回调
    /// </summary>
    /// <param name="sender"></param>
    privatevoid cdTweenCompleted(dfTweenPlayableBase sender)
    {
        var slot = sender.transform.parent.GetComponent<SpellSlot>();
        slot.IsSpellActive = false;
 
        var cdSprite = sender.GetComponent<dfSprite>();
        cdSprite.IsVisible = false;
    }
 
    /// <summary>
    /// 代码加入补间动画组件,并人为设定特定值。
    /// </summary>
    /// <param name="go">被添加组件的GameObject</param>
    /// <param name="timeLenght">补间动画播放时间</param>
    /// <returns></returns>
    privatedfTweenFloat addCDTween(GameObject go, floattimeLenght)
    {
        dfTweenFloat cdTween = go.AddComponent<dfTweenFloat>();
        if(cdTween)
        {
            cdTween.TweenName = "Fill";
            cdTween.Target = newdfComponentMemberInfo(); ;
            cdTween.Target.Component = go.GetComponent<dfSprite>();
            cdTween.Target.MemberName = "FillAmount";
            cdTween.Function = dfEasingType.Linear;
 
            #region  纯粹秀一秀自定义曲线的写法
            //Keyframe keyframe;
            //AnimationCurve curve = new AnimationCurve();
            //keyframe = new Keyframe(0.0f, 0.0f, 0.0f, 5.0f); curve.AddKey(keyframe);
            //keyframe = new Keyframe(1.0f, 1.0f, -2.0f, 0f); curve.AddKey(keyframe);
            //cdTween.AnimationCurve = curve;
            #endregion
             
            cdTween.LoopType = dfTweenLoopType.Once;
            cdTween.Length = timeLenght;
            cdTween.StartValue = 1f;
            cdTween.EndValue = 0f;
        }
        returncdTween;
    }
 
 
    voidOnDestroy()
    {
        for(inti = 0; i < slots.Length; i++)
        {
            slots[i].GetComponent<dfControl>().Click -= OnClickSpell;
        }
    }
}
还有子弹(也就是蓝色箭头的)的脚本
[C#] 纯文本查看 复制代码
?
01
02
03
04
05
06