三七互娱笔试记录

Unity3D游戏开发岗笔试 笔记

目录

C#中的委托是什么?事件是一种委托吗?

什么是协同程序?

Heap与Stack的区别

数组中存放了某一类型得到数据集合,用泛型实现对这个数组的排序

StringBuilder和String的区别

Animation和Animator的区别

Unity3D脚本从唤醒到销毁有一套比较完整的生命周期,例举出系统自带的方法。

Unity3D动态加载资源的方式

Unity内存优化的方法(至少五种)

什么是AssetBundle?谈谈你对AssetBundle内存分配情况的理解。

谈谈你对3D渲染管道的理解。

下列代码,会出现什么问题?为什么?


C#中的委托是什么?事件是一种委托吗?

委托本质上是一种“方法接口”,它相当于C/C++中的函数指针,但比函数指针安全,在C#中通常用于事件处理。事件不是委托,不过由于事件的性质决定了处理它的程序逻辑能访问的参数,因此,在C#中处理事件的逻辑都包装为委托。

委托的简单运动:

//第1步:声明一个委托

public delegate void CalculateDelegate(int x, int y);

//第2步:创建与委托关联的方法,二者具有相同的返回值类型和参数列表

public void Add(int i, int j)

{

    MessageBox.Show((i+j).ToString());

}

//第3步:定义委托类型变量

private CalculateDelegate myDelegate;

 

public void GetDelegateEx()

{

    //第4步:进行委托绑定

    myDelegate = new CalculateDelegate(Add);

    //第5步:回调Add方法

    myDelegate(1, 2);

}

 

什么是协同程序?

协程是在主程序运行时同时开启另一段逻辑处理,来协同当前程序的执行。换句话说,开启协同程序就是开启一个线程,但是协程并不是线程。

在Unity3D中,使用MonoBehaviour.StartCoroutine方法即可开启一个协同程序,也就是说该方法必须在 MonoBehaviour 或继承于MonoBehaviour的类中调用。

协程是一个分部执行,遇到条件(yield return语句)会挂起,直到条件满足才会被唤醒继续执行后面的代码。

Unity在每一帧都会去处理对象上的协程。主要是在Update后去处理协程(检查协程的条件是否满足)。

扩展:线程和协同程序的主要不同在于,在多处理器情况下,从概念上来讲多线程程序同时运行多个线程;而协同程序是通过协作来完成,在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只在必要时才会被挂起。

 

Heap与Stack的区别

内存分为两类,一类是栈内存,一类是堆内存。

栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。

堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用 new创建的对象都放在堆里,所以,它不会随方法的结束而消失。 方法中的局部变量使用 final修饰后,放在堆中,而不是栈中。

 

1.heap是堆,stack是栈;

2.stack的空间由操作系统自动分配和释放,heap的空间是手动申请和释放的,heap常用new关键字来分配;

3.stack空间有限,heap的空间是很大的自由区;

4.若只是声明一个对象,则先在栈内存中为其分配地址空间,

  若再new一下,实例化它,则在堆内存中为其分配地址。

 

数组中存放了某一类型得到数据集合,用泛型实现对这个数组的排序

使用委托进行排序的条件设置。

public delegate bool Compare(T  t1,T  t2);

publc void Sort(T[] array,Compare del)
{
    for(int i=0;i(array,Compare(t1,t2){return (t1-t2)>0;});
}

StringBuilder和String的区别

String对象是不可改变的,每次只能赋值一次,在每次改变时,都会生成一个新的字符串令原有的对象引用新生成的对象;

StringBuilder每次的操作都是对自身的对象进行操作,其所占的空间会随着内容的增加而扩充。

在做字符串的操作时,需要大量进行修改增加的操作时,为了避免生成许多不必要的匿名字符串对象影响性能,一般都使用StringBuider,如果对字符串只进行一次或少量操作,使用String就行。

 

Animation和Animator的区别

Animation和Animator 虽然都是控制动画的播放,但是它们的用法和相关语法都是大有不同的。Animation 控制一个动画的播放,而Animator是多个动画之间相互切换,并且Animator 有一个动画控制器,俗称动画状态机。

Animator 利用它做动画的切换是很方便的,但是它有一个缺点就是占用内存比Animation大。

 

Unity3D脚本从唤醒到销毁有一套比较完整的生命周期,例举出系统自带的方法。

Awake->OnEnable->Start->FixedUpdate->OnTriggerXXX->OnCollision->Update->LateUpdate->OnGUI->OnDisable->OnDestroy->OnApplicationQuit

 

Unity3D动态加载资源的方式

1、Resources.Load()

把需要用到的资源全部放入名为Resource的文件夹里,需要调用的时候则通过方法调用;

2、AssetBundle.Load()

把对象打包成asset bundle格式,上传到本地磁盘或者服务器上,然后通过WWW模块在服务器端把需要的资源下载下来,在场景中进行资源的加载。

 

Unity内存优化的方法(至少五种)

  1. 压缩自带内库;
  2. 使用对象池,把不需要使用的对象先隐藏起来,减少对象的实例化;
  3. 释放AssetBundle占用的资源;
  4. 降低模型的片面数、降低模型的骨骼数量、降低模型的贴图大小;
  5. 使用光照贴图、使用多层次细节、使用着色器、使用预设体。

 

什么是AssetBundle?谈谈你对AssetBundle内存分配情况的理解。

这个看的很懵,链接在这里,大家可以参考一下:https://blog.csdn.net/cyxisgreat/article/details/8761877

 

谈谈你对3D渲染管道的理解。

参考自:https://blog.csdn.net/nliki/article/details/51822812

渲染管道是指在显示器上为了显示出图像而经过的一系列必要操作。

分为三个阶段:应用程序阶段(CPU)、几何阶段(GPU)、光栅阶段

应用程序阶段在CPU里进行,把模型的顶点坐标、纹理等数据计算之后传给GPU;

几何阶段在GPU进行,传入GPU的坐标是物体的局部坐标,每个顶点的坐标都是以自身为坐标系的坐标,这个时候需要进行四个阶段的坐标转换:局部坐标系-->世界坐标系-->观察坐标系-->视口坐标系,使模型在转换绘制完成之后可以在2D的屏幕上看起来有3D的效果。

坐标转换后模型会被分割成多块三角片,对三角片进行裁剪(包含视域裁剪、视口裁剪、背面剔除)后进行光栅阶段。

光栅阶段则是对于三角片进行着色,遮挡剔除。

 

下列代码,会出现什么问题?为什么?

public static void Main()

{

    List arr=new List (new int[] {1,2,3,4,5,6,7});

    foreach(int item in arr)

    {

        Console.WriteLine(item);

        arr.Remove(item);

    }

}

上述代码会在第二次调用迭代器的时候抛出异常,因为在使用迭代器时,不允许对容器的内容进行更改,在对容器更改之后,迭代器会报错(个人理解,有错误希望在评论指出,小弟一定更改)。

你可能感兴趣的:(面试题总结)