腾讯光子客户端开发实习岗一面面经
腾讯会议 90分钟+
前情提要:投天美技术群面挂了,光子秒捞(感谢!!)
1.简单减少下自己吧
对着简历巴拉巴拉
2.有看到你在游戏开发时使用了很多技术,可以讲讲有哪些技术吗?
脑子抽了:(
说根据需求开发功能,并使用与之对应的技术或组件;动画、碰撞检测系统、脚本逻辑算吗,对象池之类的(面试官问有没有具体的,回答完之后笑了笑)
3.刚刚你提到了很多技术,有哪些是比较熟悉的,能具体讲讲吗?
说根据需要使用,没有说哪种特别熟悉;
4.那就说说对象池吧,看你用到了对象池,具体原理和优劣?
将暂时不使用的物件(prefab)禁用并扔到对象池保存起来而不是销毁,在需要时再从对象池get出来激活并初始化,能够降低性能损耗
5.具体是如何降低性能损耗的呢?
尬住了,没有考虑过这个问题;
先说了下可能降低内存损耗吧,看面试官的神情语气应该不对,仔细想了想,觉得是在new(创建)和delete(销毁)的时候会调用类的构造和析构函数,那么CPU就要分配部分计算资源去执行这些函数,而如果采用对象池,不需要这些步骤,需要的时候从内存调过来就行,节省了CPU计算资源。
6.那具体是用什么数据结构实现的对象池?
在我最近做的这款肉鸽游戏中有用到,主要是通过字典+链表的方式,字典的key存预制件名,链表则插入一个个预制件实例,当需要生成物体时,先去字典中访问是否有,若有则直接从池子调用,若没有则new一个新的,销毁时将物体放到池子对应的链表中;(说了下缺陷)因为是比赛,时间比较赶,就没做优化,后来想想其实有问题,当某一时间段大量访问对象池时,池子没对象就会new很多个对象,而后续如果不再使用,那么对象就会留在池子了占内存
7.刚刚你说了这些缺陷,那有没有什么办法解决?
想了想,可以通过动态更新的方法,使用空间局部性原则,当一段时间池子中某一对象使用频率较少时,预估后续使用频率也较少,可适当减少池中对应链表中的元素个数(渐进式减少)
8.你有提到资源卸载,说说他的原理吧
可以用到Resources.load做资源的动态加载,不必在编译时知道需要加载什么资源,卸载的话同样用到Resources
9.那比如我有很多子弹飙血特效,我该如何对卸载这个资源特效?什么时候卸载呢?
有点说不清楚,还是举个栗子吧!
在我做的肉鸽项目里,也有很多子弹特效(粒子特效),每个粒子特效都会有生命周期,当生命周期结束时,再把粒子特效丢进对象池子里,等待下一次获取,而当场景切换时,再统一卸载对象池中的资源。(这方面感觉还需加强)
10.看了下你简历中提到的序列帧动画和碰撞检测,具体是怎么实现的?
得到允许后打开了ppt,播放了一下彼界赐福的实机演示,说碰撞检测主要通过unity中的box collider组件,通过onCollisionEnter获取到所碰撞的Boss对象,再执行对应的操作。
11.都是用的box碰撞器吗?unity还有哪些碰撞器(追问)?
还会用到capsule collider,还有像刚提到的box,sphere,line,mesh等(忘记3D物体的碰撞器了,晕)
12.刚刚看到你的这个boss,他具体的动画切换是怎么完成的?
将ppt翻到有限状态机那一页,实际上是通过Animator controller完成的,controller中有很多个动画状态,当满足状态转移条件时便会切换状态,但实际上我写的时候自己搭建了一套boss的有限状态机,当程序执行切换操作时,会给Animator对应的消息变量(bool,trigger等),使得Boss的动画能够相应的切换。
13.项目中有用到什么寻路算法吗,有了解过什么AI寻路算法吗?
这个项目中因为是横版2D嘛,怪物移动只在x轴上进行,所以不太涉及什么复杂的算法,如果是涉及二维或三维的寻路,可能要用到DFS,BFS或是A*算法;
14.能聊聊A*算法吗?
A*算法是一种寻路算法,也是求最短路径,在每次选择下一个路径节点时,不仅仅要考虑当前节点去往该节点的代价,还需要加权该节点到终点的启发式代价,通常的启发式函数会用到曼哈顿距离或者欧式距离。
15.好,那接下来问你一些有关计算机网络的知识,你知道TCP和UDP吗?区别?
T传输C可靠P协议,传输可靠协议,所以他是可靠的建立连接的面向字节流的,而U用户D数据包P协议,用户数据包协议,是不可靠非连接面向数据包的
16.那么在咱们开发游戏的时候,用哪个比较好?
TCP吧,毕竟是面向连接可靠的,谁也不想传输的时候丢一两个包导致卡顿延迟
17.那比如说当前一帧我要发送大量的数据,用TCP会有什么问题?或者说TCP相较于UDP的不足之处是什么?
当时有点不知道这是问什么,就答说TCP因为有三次握手四次挥手以及流量控制拥塞控制,可能相比UDP开销会更大一点。(可能是想说TCP有流量限制不能一次性传太多帧,所以需要多个TCP连接?)
18.进程和线程的区别在哪里?
进程是操作系统分配资源的基本单位,线程是操作系统进行资源调度的基本单位,一个程序可能有多个进程,一个进程可能有多个线程。
19.有了解过游戏开发中的多线程吗?
还真没了解过,只用过协程做过开发。
20.那你想想看,多线程的应用场景会有哪些?
真有点蒙蒙的;
比如说进行工作分工?一个线程管数据,一个线程管交互逻辑,一个线程管显示(答道MVC那边去了),场景的话A发射子弹击中B,C看见的飙血的过程之类的?(总之是真没怎么用过,mark一下回去好好学学)
面试官:多线程其实在游戏开发中非常常见,刚刚资源卸载就用到了,可能是因为引擎帮你封装好了操作,所以你不太了解)
我:滑轨...
21.问问数据结构和算法吧,你知道空间条件树吗?(应该是这个名字)
没有太用过和了解过,是用于碰撞检测判定的吗?将空间分割成多个子空间,然后只检测单个子空间中的碰撞物体。
22.那不能两两进行碰撞检测吗?(追问)
不行呐感觉时间复杂度有点高(看我不太了解这块就没问的太深)
23.遍历n个元素的数组和链表,哪个比较快?
秒答数组,遍历时Cache缓存命中率比较高,空间局部性原则
24.既然你提到Cache,那是什么?
高速缓存(应该是这个名吧),主要是解决内存和CPU之间读取速度不匹配的问题
25.Cache具体是怎么工作的,怎么和内存合作?
当CPU打算访问某个数据时,会先去多级Cache中尝试寻找数据是否存在,l1 l2 l3,若找不到,再从内存中找(忘记说会进行Cache块替换了,缓存一致性了)
26.既然提到了内存,你知道虚拟内存吗?
每个进程都会有独立的虚拟内存地址,对数据的读写操作都是基于该虚拟内存地址,操作系统则负责将虚拟内存地址映射到物理地址当中,本质是将部分虚拟内存放在磁盘上,进而能使用比物理内存更多的存储空间。
27.提到了磁盘,内存和磁盘是怎么合作的?若内存中没找到数据会怎么样?
若没有找到数据,会引发缺页中断阻塞当前进程,并从磁盘调页。(没有问有什么替换算法)
28.问问语言类的吧,你是主用Csharp的吧,还会什么语言?
写游戏的时候会用到Csharp,平时做实验的时候会用python和C++
29.那C++和Csharp有什么不同吗?
绝大部分情况Csharp不支持指针,而C++支持;编译速度来看C++更快;C++会将代码编译成汇编语言,再转换成机器语言,Csharp则先编译成中间语言IL,链接CLR(公共语言运行库),再编译成机器语言;C++是不仅仅是面向对象的,而Csharp是是面向对象的;UE主要用C++,Unity主要用Csharp(笑)23. 谈到指针,指针是什么?可以用来干什么?
指针就是指向数据的地址,比如在函数中我想修改输入变量值,可以传递指针,通过指针修改。
30.那Csharp中的函数没有指针,是怎么修改输入值的?
简直是给自己挖坑,压根没想过这个问题:(
答道,平时写的时候,都是可以直接在函数中修改输入变量的值的,猜测输入的应该是该变量的引用,所以可以直接修改。
31.了解堆栈吗?C++和Csharp分别是怎么使用堆的?有什么区别?
卡主,真是好好想了想;
C++通过new创建新对象实例并调用其构造函数,Csharp也是通过new;销毁时C++会要通过手动delete释放内存,Csharp的话写游戏脚本的时候就没释放过内存,推测应该是Csharp的GC垃圾回收机制自动帮我释放了内存。
32.了解C++的虚函数吗?具体是怎么实现的?
了解,虚函数是C++实现多态的重要机制,主要是通过构造类的虚函数表实现的。
33.那构造函数和析构函数可以是虚函数吗?
构造函数应该不能为虚函数,因为虚函数本质是为了实现多态机制,而执行构造函数时会先执行父类构造再执行子类构造,此时子类尚未更新虚函数表(或是未定义),那么虚函数便不能达到预期的多态,没有意义。(感觉这里还是有点混淆,得加强)
析构函数一般是虚函数,假设现有一父类指针指向派生类对象,delete该对象,如果父类析构函数不为虚函数,则会调用父类析构而非派生类析构,导致一些错误麻烦(这里卡主了,没想出来麻烦是什么)
34.时间也不早了,考你一道编程题吧!m个技能点数,n个技能,每个技能有对应的学习点数要求以及技能伤害,问最大伤害值是多少?
走到这已经是头昏昏沉沉,又有点紧张,因为面试官说时间有点晚了,就只给10-15分钟做题时间,没想出什么特别好的办法,就想着排序贪心的思想,不出意料的没写完。
然后
面试官:你就说说自己的想法吧
我:按性价比排序,贪心策略
面试官:那你看看用例3,用你的办法做是不是有些问题
我:!还真是,寄!!
面试官:好好想想,如果不能用排序贪心,还有没其他办法
我:(灵光一闪)dp吧
面试官:哦?那你说说怎么dp
我:叽里咕噜%&#@...(没说出个所以然来),说不出来,能不能给我点时间把他写完
面试官:不必啦,解释下什么时候用dp比较好
我:当前状态能够通过状态转移,从前一状态得到,并需要记录中间值时可以用到
面试官:这道题还能用DFS和BFS,与之相比dp的优势是什么?
我:思考ing,时间复杂度都是O(n^2),空间复杂度dp只用一维数组存,会低一点吧
面试官:你要不再好好想想
我:努力思考ing,真想不到了(好吧原来是dp会少遍历一些不必要情况,时间复杂度更低,最近没复习算法题的恶果)
35.聊点轻松愉悦的吧,有玩过什么游戏吗?
直接打开电脑上的steam库,如数家珍,还提到玩过一点fps,感觉面试官眼睛亮了
36.有玩过什么fps游戏吗,具体说说?
CF,CS,OW,PUBG,APEX,瓦...,不过由于我动态视力不行,像大逃杀之类的游戏体验感很差,就没怎么玩31. 最近有玩过瓦吗
没了,只看瓦的比赛,EDG(看样子面试官很喜欢瓦,又或者我面的这个项目组准备开发瓦手游?)
37. 玩游戏给你带来了什么?你最看重游戏的哪些点?
说了下一个是在游戏中付出是真的能有回报,游戏不会亏待每一位玩家;一个是比较看重剧情,享受每个故事带给我们的悸动;还比较喜欢玩一些独立游戏,学习借鉴一下独有创作者的逆天脑洞。
38.为什么选Unity?为什么想成为游戏开发者?怎么踏入这个行业的?
当时本科有一帮很喜欢玩游戏,有很多奇思妙想的小伙伴,一拍脑袋说做个游戏吧,又因为团队里没什么人有开发经验,自己有点编程基础,就担任了团队开发的职位;当时也是有小伙伴说Unity好上手,不怎么吃设备,就学习了这款引擎;后来也是打比赛做了第一款自己的游戏《模拟剧场》,这游戏脑洞清奇有点幽默,而每天和左边的室友兼策划Battle,实现一些奇思妙想的功能真的很有趣,后面也上线了嘛,也得到了很多正反馈,就感觉将一些天马行空的想法落地实现,并收获大家反馈的过程很有成就感和满足感,很棒,我想这也是我坚持下去的动力吧。
39. 有什么职业规划吗?
因为开发的游戏规模都比较小,很多技术(多线程,lua热更新,shader等)都理解的非常浅薄,所以想在实习期间能够多接触学习这些技术,同时也了解整个游戏产品是如何从立项、策划、开发、上线、运营的,后续的话想通过一到两年的时间做gameplay,锻炼代码技术,再往引擎或是渲染管线计算机图形学这方面发展吧
40. 我们游戏开发这边在深圳,可以接受吗?
问了下是不是深大旁边十字路口的那座双子星,说好像不是,在科兴路,离深大也近,双子星好像是toB部门什么的。就说也挺好,以前在深大呆了四年,对南山也比较熟悉。
41. 有了解过图形学,渲染关系管线之类的知识吗吗?
看过一本关于shader的书,了解整个渲染管线的流程,也刷过games的部分视频,写过shader脚本(简单),总的来说还是入门级,以后也想向这方面深造
反问
1.我目前的一些不足吧,有什么提升点吗?
建议是多了解游戏引擎的底层逻辑,无论是通过百度还是AI什么的,这会对你日后的游戏开发有很大帮助
2.游戏比赛开发的demo和商业化游戏产品的区别主要是什么?
demo更注重的是设计的框架,想法,而商业化游戏使用的技术往往会更加成熟
3.作为实习生,在实习期间最需要学习的是什么?
与策划、美术沟通,与其他程序佬协作完成项目的技巧;了解游戏开发的一些基本常识,性能更优的技术,以及了解整个开发流程。
谢谢!
总结:
总的来说鹅厂对基础真的很重视,八股覆盖的很全面,而且会根据你的回答进一步深挖问题,当然也会对你的项目狠狠进行拷打。
面试官人真的不错,在你需要思考的时候会给予你时间,在你很是纠结的时候会引导你方向,在你实在不懂的时候会为你答疑解惑,还会耐心和你一起讨论问题,大厂不愧是大厂。
经验:C++以及408一定一定要过关,要熟悉自己写过的项目(有条件的话可以用视频或ppt的形式讲解其中的技术点,会让面试官很直观的了解到你的工作);当然项目是加分项,如果会点渲染管线相关的就更好了。
11点面的试,12点半结束,两点半就收到二面邀请了,速度好快,大厂不愧是大厂。
发发面经攒攒人品吧!求求啦让我上岸吧!!
#软件开发笔面经#