super1 发表于 2021-5-26 17:17

一些Unity面试题

记录一些自己面试遇见的问题吧,通过面试也可以发现自己和大佬们之间的一些差距,方便对自己的查漏补缺。如果后面在学习的过程中遇到一些好的知识点,也会记录一下,万一自己哪天有本事当上面试官了,这不就是题库了,哈哈。
个人感觉关于U3D方面的面试主要分如下四大块:
Unity功能相关,主要结合面试者简历上介绍的一些功能模块,了解对Unity的使用情况,例如Timeline,Assetbundle,各种Package,以及一些性能优化等等。语法相关,例如C++,C#,Lua,HLSL/GLSL。算法相关,可以了解面试者的逻辑能力,脑子灵不灵光。图形学相关,可以了解面试者对渲染方面的知识掌握。


Unity功能相关

这块没什么好说的,在团队里每个人负责的模块都不一样,如果自己连自己写在简历上的模块都说不清的话,还是洗洗睡吧。
当然了,很多模块可能是你一年甚至更久前做的,如今忘得一干二净,临时要能把它说的清清楚楚也是蛮困难,反正我肯定不行。俗话说:好记性不如烂笔头,建议大家可以像我一样平时把划水摸鱼的时间抽一部分出来,记记笔记。这样一方面可以加深自己的理解,另一方面在以后需要它的时候,可能较快的回忆起来。还有比如我不会的,但是你会,这样我不就可以百度到了,嘻嘻。
性能优化可参考:


语法相关

语法也是非常重要的,也是自己很欠缺的一部分。大部分的U3D程序员应该都是用C#做开发,如果你不能很清晰的了解class与interface,delegate与action,sealed和virtual等等的适用场景,那么在需要搭一些框架的时候,可能会写的奇臭无比。
还有就是C++,也是我的惨痛经历,由于长期使用C#做Gameplay,导致几乎没用过C++,因此想加入某大厂的一丝丝希望也破灭了。很多大厂都会有引擎开发部门,而且Unity也是一个C++引擎,因此如果不会C++那么压根不能看懂Unity的一些底层代码,从而去修改优化。因此今后划水摸鱼的时间又得抽一部分出来学习C++了。
学好C++,走遍天下都不怕。
废话说了这么多,来正式看看一些有关的面试题:
1. C++的多态原理

不仅仅是简单的基类声明函数时使用virtual关键字,然后在派生类重新函数体。既然是原理,就要挖的更深,里面涉及到了虚函数表,以及对应基类的析构函数没有设置virtual关键字的话,就可能导致内存泄漏。
参考:


2. Lua中 ipairs 和 pairs 的区别

简单来说,pairs 会遍历表中全部的键值对(key,value),其中键可以是字符串也可以是整数(例如:array['wjr'],array)。而 ipairs 则从下标为1开始遍历,然后下标累加1(例如:array,array,...),如果某个下标元素不存在就终止遍历。
这就导致如果下标不连续或者不是从1开始的表,如果使用ipairs 遍历就会中断或者遍历不到所有元素。


3. Lua实现面向对象

LUA中的类可以通过 table + function 模拟出来,而类的继承,可以通过 metetable 模拟出来。
参考:
4. Lua中require的原理

简单来说,当我们要require一个 .lua 文件的时候,首先会查找package.loaded表,检测是否被加载过(预防重复加载)。如果被加载过,require得到之前保存的值,即:package.loaded['name']。
如果没有被加载过,则通过package的searchers表中的四个加载器进行查找,四个加载器按顺序查找,找到则返回得到的结果,没找到则执行下一个加载器。
预加载器,执行package.preload,一些特殊模块会有预加载器。lua加载器,查找 package.path 路径下的文件。c加载器,查找 package.cpath 路径下的文件。一体化加载器,本质上他是cpath加载器的延伸,允许多个导出函数绑定在一个c库里。
参考:


5. CLR机制

参考
算法相关

想要算法好,无脑刷力扣:
虽然平时一些功能,即使用简单的 if/else,循环,递归等也能实现,但是好的算法可以大大提高程序的运行效率,降低内存的消耗等,也能让你觉得自己很牛,得到爽快感。
1. 自动寻路的原理

很多游戏都会有自动寻路,如下图:
哈哈,这个寻路是不是感觉很离谱,碰巧今天看见帮里人发,最好玩的是,挨骂的居然还是策划,玩家眼里策划真是神一样的存在。
如今常见的寻路有A star,D star,Dijkstra等算法,正好看见一个牛逼的网址,可以看出各种算法的计算过程:
A*算法
算法原理参考:
感觉很值得研究,有空一定自己实现一下。


2. 排序算法

最常见的就是问快速排序了,百度一下一大堆,就不多说了
参考:


3. 最大公约数

这么不起眼的题,有三个算法,参考如下:
想到自己当时 freestyle 的回答:搞个循环从2开始慢慢往上除,卧槽,真想找个坑钻进去。


4. 斐波那契数列(Fibonacci sequence)

斐波那契数列简单来说,就是一个数组 array,我们可以自定义 array 和 array 的值,然后数组后续的值都等于前两项之和,即array = array + array,那么怎么求array的值。
freestyle 的第一反应自然就是循环:
int Fibonacci(int a0, int a1, int n)
{
    if (n == 0) return a0;
    if (n == 1) return a1;
    int value1 = a0;//第一个被加数
    int value2 = a1;//第二个被加数
    for (int i = 2; i <= n; i++)
    {
      //做一个换位,例如对于a2而言,valu1 = a0,value2 = a1。而对于a3而言,value1 = a1,value2 = a2。
      //其中后者的value1等于前者的value2,后者的value2等于前者的value1+value2
      int temp = value2;
      value2 = value1 + value2;
      value1 = temp;
    }
    return value2;
}实际上还有看起来更舒服的递归算法:
int Fibonacci(int a0, int a1, int n)
{
    if (n == 0) return a0;
    if (n == 1) return a1;
    return Fibonacci(a0, a1, n - 2) + Fibonacci(a0, a1, n - 1);
}不过明显可以发现,递归算法里虽然看着简洁,但是有个很致命的缺点,无限多的重复计算。时间上的漏洞,那么我们就牺牲一下空间来弥补,如下:
Dictionary<int,int> FibonacciDic = new Dictionary<int, int>();
int Fibonacci(int a0, int a1, int n)
{
    if (n == 0) return a0;
    if (n == 1) return a1;
    if (FibonacciDic.ContainsKey(n)) return FibonacciDic;
    return Fibonacci(a0, a1, n - 2) + Fibonacci(a0, a1, n - 1);
}

图形学相关

在图形学方面,自己更是一个实打实的萌新了,但是它真的很重要,能够让你看清引擎中很多功能的本质,比如缩放旋转是矩阵的相乘,物体表面的颜色有它的计算公式。


1. 用shader实现描边效果

参考:


2. 放大镜效果

最简单的方法就是新增一个Camera,然后利用RenderTexture来实现。


3. 光栅化过程以及着色模型公式等



4. 菲涅尔方程(Fresnel Rquation)

菲涅尔方程描述的是在不同的表面角下表面所反射的光线所占的比率,在BRDF中也有它的存在。具体介绍可以参考:
例如我们可以用它实现外发光的效果,下面视频是达哥使用ShaderGraph利用Fresnel Effect实现外发光的效果。
页: [1]
查看完整版本: 一些Unity面试题