前情提要
本人大学所学专业为知乎劝退专业,机械工程,毕业三年从校招时的懵懂无知到现在通过社招打怪升级进入腾讯网易等大厂工作,也积累了一定的面试经验了,特此分享一下,也算是对自己工作学习的阶段性总结了。 第一篇文章已经简单介绍了我的背景以及游戏开发入门的路线,感兴趣可以点一点下面的链接看看,这篇文章就讲一讲面试的经验吧。
首先我的工作区域主要是广深区域,所以广州深圳部分的小厂、中厂、大厂的面试都参加过,个人感觉大部分公司面试的重点都是那么几个,所以就不分公司逐个展开讲解了,比较特殊的会单独列出来讲讲,首先讲一下客户端岗位社招面试的重点吧,C++、Lua、Gameplay及项目经历、图形学,其他的内容就看你的简历上有什么内容,你做过什么内容以及面试官的方向了。好了,废话不多说,主要内容开始。
1)编程语言
要关注的是三种语言:C++、Lua、C#
首先C++永远的神(引擎底层实现基本都是C++,UE4开发也需要了解C++),Lua作为现在手游热更新的常用方案,也是需要重点掌握的,如果是做Unity开发的话,C#也是需要了解的。
1.1 C++
- 基础
- 构造函数、拷贝构造函数、析构函数的作用。构造函数和析构函数哪个能写成虚函数,why?
- 深拷贝和浅拷贝的区别,用错了会产生什么后果?
- 虚函数的实现机制
- 指针和引用
- new、delete和malloc、free的区别
- 一些常用的关键字,如const、static、inline
- STL:
- 空间配置器
- 常用STL容器及其实现原理,不同容器间的区别,如vector和list的区别,map、set的实现机制
- vector扩容机制
- hashtable(哈希表)的作用与原理
- 函数模板,全特化和偏特化
- C++11 新特性:
- 智能指针 std::unique_ptr、std::shared_ptr、std::weak_ptr
- auto关键字,全部都用auto声明变量对性能有啥影响吗?
- nullptr和NULL的区别,为啥nullptr更好
- 右值引用和移动语义,很重要
1.2 Lua
首先Lua语法很简单,跟着菜鸟教程学一下或者找本书看一下很快就学会了,主要需要
了解table的使用,Lua面向对象的实现,Lua协程,Lua元表、upvalue概念等。
比较重要同时也是面试的加分项是对Lua源码的理解,当然我是简历里面写了熟悉源码所以基本面试都问到了,但是作为客户端开发平常用的最多的语言,还是建议看一看Lua源码,代码量不多,非常值得学习,下面重点讲一下吧。
首先推荐一下Lua设计与实现这本书,写的很好。
《Lua设计与实现》
作者对应的git地址:
1.3 C#
学会C++以后再学C#还是比较简单的。
- 委托、事件的定义及用法,最好能了解实现机制
- 常用数据结构的底层实现如Dictionary、List等
2)数据结构
由于我是社招,简历上项目还是较多的,所以数据结构问的不多,我的第一篇文章大概有讲,可以参考一下,但是对于校招的同学来说还是要重点关注的。
关于刷题,这里就不班门弄斧了,leetcode搞起吧,社招相对问的会少一些,所以社招的同学不用放太多精力在这上面,我面试的时候就大概就问了一下反转链表,镜像二叉树,TopK的原理这些相对简单的算法。
3)图形学
作为游戏开发的一座大山,不管是客户端开发,还是引擎开发,都绕不过图形学的内容,这一块对于客户端岗位的面试一般不会问的很深,但是我对这一块还是比较感兴趣的,所以面试的时候也占了比较大的比重,也算是加分项吧。
- 图形学
- 渲染管线,基础中的基础了,建议先找一篇文章大致了解一下渲染管线,然后针对里面的每个知识点逐个突破,深入学习。
- 各种buffer的作用(深度缓存,模板缓存,延迟渲染的GBuffer等等)
- 标准光照模型(漫反射实现,镜面反射实现),光照衰减
- 阴影实现方案,常用的阴影实现有圆片阴影,平面阴影,ShadowMap,一般会根据项目对阴影质量的需求,设备机型等选取阴影方案。其中ShadowMap是一个比较大的概念,其原理如下:从灯光的位置往物体看,并将光源空间下的物体深度信息存入一张深度图中(数据对应于片段在裁剪空间中的Z坐标),这张深度图就是ShadowMap。然后将物体(像素)的深度与深度图中的深度进行比较,判断像素是否处于光源照射范围之内,是否需要生成阴影。
- 针对shadowMap的优化方案很多,列举一些如:
- Cascaded ShadowMap(CSM)
- Screen Space Shadow Mapping(SSSM)
- Percentage Closer Filtering(PCF)
- Percentage Closer Soft Shadow(PCSS)
- 常用屏幕后处理实现原理,如景深、模糊算法、运动模糊等等
- 常用抗锯齿算法,如SSAA、MSAA、TAA
- 前向渲染与延迟渲染的区别,这是一个比较大的概念了,建议多花点时间吃透,也能很好的加深对图形学的理解。
- PBR原理以及项目中的PBR工作流,这个简历不写的话应该不会问,我之前项目里了解过,算是比较熟悉,感兴趣的同学也可以了解一下,其实不难的。
- 经典光照模型里面,漫反射是Lambert,镜面反射是Blinn-Phong,环境光是c*(1-AO(环境光遮蔽)),而最简单的PBR,可以简单的理解为换了一个效果更好更贴近物理效果的光照模型,分为直接光照和间接光照两部分,其中漫反射本质还是Lambert,镜面反射基于Cook-Torrance模型,环境光一般是是IBL(Image-Based Lighting)。
- NPR 卡通渲染,和上面一样简历不写不太会问,感兴趣自己了解一下吧,要点如下:
- 描边
- 着色
- 边缘光
- Bloom
- 头发高光
- 面部修正
4)角色动画
- 骨骼动画原理,动画重定向原理,动作位移(滑步问题),动作融合、动作叠加的原理等
- 前向动力学FK和反向动力学IK,常用IK算法如下:
- TwoBoneIK(三角解析法)
- CCD IK(cyclic coordinate descent Inverse Kinematics)
- FABR IK(Forward and Backward Reaching Inverse Kinematics)
- 梯度下降法实现IK
- 一些常用IK算法的应用如脚步IK:
- 在脚步骨骼往上添加一点偏移,往脚底打射线(射线可以根据性能进行分级),检测是否在斜坡或者楼梯上。
- 射线如果命中某个面,根据此面的法线设置旋转脚部的Rotation。
- 根据射线检测的hit点及法线算出命中平面,取其上离Foot节点最近的点设置脚步的Position。
- 根据是否设置IK调节模型身体的中点,基本流程完成,后续优化这里就不讲了。
5)Gameplay相关
毕竟是客户端开发,Gameplay的经验还是很重要的,在大型游戏开发的过程中配表的形式是不能够完全满足策划复杂的需求的,同时很多系统如果搭配上可视化的工具会极大的提高开发效率及策划的配置效率,所见即所得是游戏开发的趋势,这篇文章讲的很好先贴一下
- 可视化节点图,一般可以制作副本编辑器等线性流程化的系统,比如我之前项目的对话及任务系统都采用了节点图的形式,编辑器一键运行即可看到效果。
- 状态机,如Unity的动画状态机就是典型的应用,状态机内部的各个状态互斥,一个状态机一个时刻只处于一个特定状态,适用于状态较少、需要进行事件状态跳转的逻辑,当状态过多时维护成本就比较高了。
- 行为树,现在稍微大点的游戏基本都少不了行为树了,重要性不言而喻,行为树这里就不介绍了,主要讲下重点内容:
- 行为树常用节点定义及作用
- tick型行为树与事件驱动型行为树的区别,两者的优劣
- 黑板BlackBoard的作用
- 与状态机的区别
- 效用AI,状态机及行为树达到的AI效果相对还是比较定制化,当希望AI会根据自己的状态产生一些相对随机的AI行为时就可以采用效用AI了
- 通用效用AI结构大致如下:
- 效用打分器(UtilityScorer):对效用行为进行打分
- 效用行为(UtilityAction):具体的行为
- 效用桶(UtilityBucket):一个桶中包含多个同类效用行为。效用打分器打分就是用于筛选出当前适合执行的效用桶类型,再选出特定的效用行为进行最终的行为触发
- 效用管理器(UtilityMgr):效用AI管理分发
- Timeline,非线性编辑系统,类似视频剪辑软件,一般用于指定剧情(过场动画),也可以进行战斗等系统的配置,一个Timeline包含多个轨道,如镜头轨,角色轨,灯光轨,自定义事件轨等,每个轨道上可以在指定的时间配置多个关键帧(打点)。
这里再说一下分层设计的概念,上述Gameplay的系统或工具往往都是搭配使用,比如最上层使用状态机维护玩家的基础状态,然后某些状态下会使用节点图进行表现,某些状态下使用行为树表达AI。
6)物理系统
这一块大部分公司问的比较少,不过当时面试库洛游戏的时候,面试的岗位是战斗开发,对这一块要求较高,所以也问了很多,这一块我了解的不太多,说说自己比较熟悉的内容吧。
- 物理
- 高速物体与细小物体碰撞有时会发生碰撞检测失效,原因:
- 1.由于碰撞物体太薄了
- 2.由于物体的移动速度太快
- 分析原因:由于在Unity中的碰撞检测是有时间花费的,而每帧之间的时间间隔大概是0.02s如果速度太快或者是碰撞物体的太薄了,下一帧可能物体已经穿过了碰撞体,没有来的及进行碰撞检测。
- 判断点是否在三角形内:
- 实际可用的碰撞检测算法,一般要分2个阶段:
- 1.broad phase 快速找出潜在的碰撞物体对列表,不在这个列表里的是绝对没可能碰撞的。broad phase确定了一批需要进一步检查的物体对。
- 2.narrow phase 准确找出发生碰撞的物体对列表。因为上一个阶段的部分物体对实际上是没有碰撞的,需要在这个阶段剔除。
- broad phase用的数据结构不一定和narrow phase用的数据结构是同一个结构。
- narrow phase会涉及到相交判定算法,如SAT、GJK
7)网络相关
基本的TCP、UDP、HTTP得了解吧,然后如果涉及到战斗之类的系统的话,帧同步和状态同步原理也得了解,这一块内容太多,贴个大佬的链接吧。
8)性能优化
这也是个比较大的话题了,CPU优化,GPU优化,脚本层优化,资源优化,UI优化网上资料也很多,这里总结一些比较重要常用的知识点。
- 场景批处理(静态批处理,动态批处理, GPU Instancing)
- 资源管理优化,纹理压缩,压缩格式,mipmap,Lod等
9)UI
很多人会忽略UI,认为UI开发很简单,但实际上UI开发过程的坑及优化也非常多,好的
UI框架设计,图集管理,各种常用控件的原理实现及封装等等,再举一些实际的例子,
比如Unity中Mask的实现原理,怎么减少UI的overdraw,循环ListView的实现,DoTween的原理及优化,Sprite Renderer的原理,TextMeshPro的原理及优点,头顶Hud怎么实现,小地图怎么实现,UGUI源码大致框架结构,太多太多了。
再说点题外话,本人是一个有一些代码洁癖的人,客户端工作中其实UI代码占的比重是比较大的,但是很多人并不重视,就瞎鸡儿写,各种粘贴复制,敏捷代码等等,给个建议,即使是UI代码也认真一点写。大家都想学的渲染确实很难,但是说到底其实也是数据的增删查改,再加一下矩阵上窜下跳的,举些例子,脏标记,批处理,深度测试,抗锯齿这些看似复杂的概念其实很多思路都可以用在UI开发里,只不过是发明者给他们加了一些很牛逼的名词而已,如果你写的好,也可以给你的代码或者框架加上很厉害的名字,自己的代码就是自己的作品,认真点准没错。
总结一下
进大厂难吗,很难,但是实际上东西就那么多,好好准备,关注细节与深度,一切都不是问题,最后,祝大家都有光明的前途(求赞啊)。 |