多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

B站游戏开发笔试卷深度复盘:从C++到Unity的考点解析

B站游戏开发笔试卷深度复盘:从C++到Unity的考点解析 2019年秋招季我投的那批游戏公司里B站的笔试算是给我印象最深的一份。不是因为题目最刁钻而是它的考察面铺得很开前面还在写C的虚函数析构题转眼就让你手推旋转矩阵最后还得蹲在一道寻路算法上慢慢磨。后来我自己带Unity项目再回头翻这份「哔哩哔哩2020校园招聘游戏开发笔试卷一」才真正看懂它考的内容一点都不虚——几乎每一题都能对应到游戏客户端日常开发里会遇到的真实问题。这篇复盘我从笔试完一直断断续续写到今天把卷子的底层逻辑、核心考点、典型题目和解题思路完整拆一遍。同时也想借这份卷子聊聊游戏开发这个岗位在校招阶段究竟应该怎么准备。无论你是正在备战秋招的应届生还是刚决定走游戏开发这条路、还在纠结先学Unity还是先学Godot的同学这篇东西应该都能帮你省下不少自己摸索的时间。1. 这份笔试卷的底层逻辑B站游戏开发岗到底要什么人1.1 笔试不是刷人而是筛选底层能力说实话校招笔试这一关多数公司并不指望你答满分。笔试的本质是快速筛掉两类人一类是基本功不扎实的一类是游戏领域知识完全空白的。B站这份卷子尤其明显它没有太多偏题怪题考的就是你平时有没有真正动手写过代码、跑过Demo、翻过官方文档。当时我拿到卷子先扫了一遍整体结构分四块选择题、算法编程题、数学与图形学题、引擎与网络简答题。时间两个小时题量不算大但每道题都要写出清晰思路想蒙混过关几乎不可能。尤其编程题卷面要求是从零写完整实现不是LeetCode式的只补一个函数这种形式反而更接近真实开发节奏。我理解这类公司出卷的逻辑他们找的不是做题家而是能直接上手干活的潜在同事。游戏开发岗和普通软件岗最大的不同是你面对的是一个每帧都在变化的实时系统——性能、内存、渲染、物理、网络、输入所有问题都挤在一个游戏循环里。笔试里那些看似基础的题目本质上都是这个系统的零件。1.2 B站游戏业务的特点决定了考察方向这里得补一个背景。B站的游戏业务长期以二次元品类为主代理过FGO、碧蓝航线这类产品后来也在做自研项目整体技术栈集中在Unity引擎上客户端几乎都是C#加Unity服务器侧偏Java或Go。这个背景直接决定了笔试的出题偏好——卷子里的C题目考的是通用编程功底而C#、Unity生命周期、资源管理、网络同步这些才是跟岗位真正相关的内容。所以如果你冲着B站游戏开发岗去复习重点会有明显倾向Unity引擎机制要多花时间资源管理和渲染优化是常见考点网络同步概念也要有基础认知。反过来如果对Unity一无所知只靠刷算法题冲过笔试后面的技术面大概率也会露馅。这也是我一直建议的游戏开发学习路线上引擎实战和算法基本功最好同步推进不要偏废。做这份卷子时我感受最深的一点是它其实在利用笔试的机会帮考生把“游戏程序员的知识地图”重新梳理了一遍。语言、数据结构、算法、数学、图形学、引擎、网络每一个模块都是日后开发绕不开的。所以就算你不投B站这份卷子的考点结构也有很好的参考价值。1.3 试卷结构一览四类题型怎么配比题型大致占比考察目的典型内容选择题30%语言与基础概念的快速判断C多态、STL复杂度、数据结构的性质编程题30%代码实现能力与算法思维单例模式、BFS寻路、动态规划数学与图形学20%底层数学功底与渲染原理旋转矩阵、点积叉积、渲染管线步骤引擎与网络简答20%实际项目中的工程经验Unity生命周期、帧同步与状态同步这个配比并没有过度偏重算法反而给图形学和引擎留了相当大的比重。对准备不充分的人来说这是最容易失分的区域对真正做过游戏项目的人来说这又恰恰是最容易拉分的地方。2. 核心考点拆解从题目反推复习重点2.1 C与C#语言功底是第一道坎先说占比较高的语言基础。B站这份卷子里的语言题大量集中在C上原因很简单——C在游戏行业的积累太深中间件、引擎底层、服务器核心几乎都离不开它。考察的知识点非常经典虚函数与多态、内存管理、STL容器时间复杂度、左值右值与移动语义、智能指针。我记得其中一道选择题大概是这样一个基类指针指向派生类对象delete这个指针时会发生什么如果基类析构函数不是虚函数派生类的析构逻辑就不会被调用可能造成资源泄漏。这道题单独看不难但背后考的是你有没有深入想过对象生命周期。游戏客户端里到处都是动态创建的对象一个析构函数漏写virtual轻则内存泄漏重则出现诡异崩溃。这类问题出现在笔试中本质是在考察底层意识。C#题目占比虽然不如C但编程题一般会有一道明确要求用C#实现因为Unity开发必须用C#。我做题时的感受是如果你平时老老实实用Unity写项目这些题目基本都在舒适区如果只是临时背概念一上代码就露怯。我的建议是C和C#都要练但练法不同。C重底层和内存模型C#重语言特性与Unity API的结合。2.2 数据结构与算法笔试的主战场算法题永远是校招笔试的大头。B站这份卷子编程题里至少出了两道算法题一道偏搜索一道偏动态规划而且都套了游戏化的外壳。这一点很值得琢磨它考的不是刁钻到只能在OJ上过的题目而是实用主义色彩明显的题。举个例子其中一道题类似这样网格地图上从起点到终点格子中有障碍物要求找到最短路径。这不就是游戏里最常见的寻路场景吗A当然能用但笔试现场我更建议先用BFS写一版因为BFS在等权图上天然能求出最短路代码量少不容易出错。如果状态好可以在注释里补一句“实际工程中会改用A加二叉堆优化”这样反而显得有实战经验。动态规划那道题被包装成“角色升级所需经验的最小花费”之类的场景。遇到这种题我的经验是别被游戏背景带偏先抽象状态转移方程。比如dp[i]表示升到第i级的最小花费转移时枚举上一次等级。一旦抽象出来剩下的就是写循环。B站考题的游戏化包装其实在暗示一个方向——你平时做的游戏Demo越多读这种题面就越轻松。2.3 游戏数学与图形学区分度最高的部分如果说语言和算法决定你能不能过线那数学和图形学决定你能不能拿高分。B站这份卷子的图形学部分不是简单的概念背诵而是要求你实际动手算。有一道简答题要求写一个二维旋转矩阵把向量绕原点旋转90度。看起来很简单但你必须记得cosθ和sinθ的组合位置。我那一瞬间其实有点慌因为平时在Unity里都是直接调transform.Rotate数学公式很久没手推了。好在基础还在列出来就是标准形式。这里给后来人一个非常实在的建议游戏开发岗笔试的数学图形学部分躲不掉。需要掌握的内容其实比想象中少但必须熟练到能默写向量点积、叉积及几何意义矩阵与向量相乘、复合变换四元数与欧拉角的区别和适用场景渲染管线中MVP变换的流程经典光照模型的基本公式深度缓冲、背面剔除的原理这些内容平时在Unity里确实用得少因为引擎都封装好了。但笔试考的就是你“即使引擎不存在也能理解底层发生了什么”的能力。这种能力在工作里的价值在于遇到渲染异常、模型闪烁、光照不对你能从原理出发排查而不是玄学式改参数。2.4 引擎与网络客户端开发的硬实力引擎相关题目在B站这份卷子里占比不低主要围绕Unity。常见考点包括MonoBehaviour生命周期函数执行顺序、碰撞检测与触发器的区别、Prefab与AssetBundle的管理、UI刷新机制、协程与异步编程。生命周期那道题几乎是必考的。Awake、OnEnable、Start、Update、FixedUpdate、LateUpdate、OnDisable、OnDestroy这个顺序如果你没亲手写过项目很容易记混。笔试答题时最好能写出顺序并且说明每个阶段适合做什么——比如Awake用于初始化引用Start用于所有对象就绪后的逻辑FixedUpdate用于物理相关更新。我在这道题上吃过亏后来带新人都会让他们自己画一遍生命周期图再讲一遍比死记硬背高效得多。网络部分考了一道经典问题帧同步和状态同步各自的特点与适用场景。B站游戏以实时战斗类为主这题几乎是必考。帧同步适合多人实时对战逻辑一致性强、带宽小但反外挂和断线重连更复杂状态同步以服务器为准客户端表现灵活、调试容易但实时性弱。让我真正理解这个问题是后来自己写了一个小联机Demo用状态同步实现两个角色互相移动才体会到为什么它会被反复拿出来考。3. 典型题目复盘与完整解题思路3.1 编程题一单例模式的线程安全实现B站笔试卷一的编程题第一题是手写单例模式要求线程安全且高效。这道题在游戏开发里非常常见因为音频管理器、UIManager、资源管理器几乎都是单例。我当时的写法是双重检查锁定加volatile以C#为例public sealed class AudioManager { private static volatile AudioManager instance; private static readonly object locker new object(); private AudioManager() { } public static AudioManager Instance { get { if (instance null) { lock (locker) { if (instance null) { instance new AudioManager(); } } } return instance; } } }写完后我补了两句说明外面的空判断是为了避免每次调用都进入锁提升性能锁内的二次空判断是为了防止两个线程同时通过第一层判断、重复创建实例。volatile关键字则是防止编译器或CPU优化导致instance在构造过程中被提前暴露。这道题的得分点不只是代码正确更在于你能不能把“为什么加双重判断”讲清楚。很多同学会写一个最简单的懒汉式单例也能跑但在批改人眼里这个细节就是区分“背过八股”和“真正理解并发”的关键。3.2 编程题二网格地图的BFS最短路径第二道编程题就是前面提到的网格寻路。我在卷子上写的是BFS完整思路分四步第一步定义队列和距离数组第二步起点入队距离置0第三步循环取出队首遍历四个方向越界、撞墙、已访问的都跳过第四步到达终点就返回当前距离。核心代码大概长这样int bfs(vectorvectorint grid, pairint,int start, pairint,int end) { int rows grid.size(), cols grid[0].size(); vectorvectorint dist(rows, vectorint(cols, -1)); queuepairint,int q; int dx[4] {-1, 1, 0, 0}; int dy[4] {0, 0, -1, 1}; q.push(start); dist[start.first][start.second] 0; while (!q.empty()) { auto cur q.front(); q.pop(); if (cur end) return dist[cur.first][cur.second]; for (int i 0; i 4; i) { int nx cur.first dx[i]; int ny cur.second dy[i]; if (nx 0 || ny 0 || nx rows || ny cols) continue; if (grid[nx][ny] 1) continue; if (dist[nx][ny] ! -1) continue; dist[nx][ny] dist[cur.first][cur.second] 1; q.push({nx, ny}); } } return -1; }BFS在这种等权网格问题里是效率与代码复杂度之间的最优平衡。相比A*少写一个启发式函数不容易出逻辑错误相比DFS不会因为搜索顺序导致“找到路但不知道是不是最短”的问题。笔试现场求稳BFS是聪明的策略。3.3 简答题Unity生命周期与帧率优化简答题部分有一道很综合的题角色血量持续下降UI血条要实时跟上要求描述从底层数据到UI表现的完整链路。这道题考的是对Unity帧循环的理解。我的回答分三层。第一层是数据层角色血量存储在逻辑组件里第二层是表现层血条UI绑定数据源或者在Update里轮询第三层是优化层如果血量变化太频繁直接每帧重建整个Canvas会造成性能浪费更推荐事件驱动——血量变化时才更新UI。这类题目没有唯一标准答案但判卷人想看的是你有没有“性能敏感”的意识。游戏开发里的很多问题不是功能性问题而是性能问题功能跑起来不难难的是在60帧约束下还能跑起来。B站在笔试里问这类问题我个人理解就是在考察项目实战积累。4. 从笔试卷看游戏开发学习路线4.1 语言与算法地基要这样打根据这份卷子的考点给准备走游戏开发方向的同学一个建议语言和算法不是刷完一轮就能扔的东西而是整个职业生涯反复使用的工具。C至少要把《C Primer》的重点章节过一遍尤其是指针、引用、内存管理和STLC#则以Unity官方文档和实际项目为主语法熟悉即可不需要钻太深。算法部分LeetCode高频题是标配但和纯互联网后端岗不同游戏开发岗的算法练习建议多往“图搜索”和“状态转移”方向倾斜。BFS、DFS、A*、简单动态规划、并查集这些在游戏逻辑里的出现频率极高优先掌握它们性价比远高于追冷门难题。4.2 引擎学习Unity、Godot怎么选近两年讨论度最高的一个话题是新人学游戏开发先学Unity还是Godot。我的观点很明确如果目标是国内游戏公司校招Unity是更稳妥的选择因为招聘岗位数量摆在那里如果你是想做独立游戏、轻量项目或者对引擎源码感兴趣Godot上手体验确实更友好场景树和脚本系统设计得很清爽。但这两种引擎不是对立关系。我带人时常说引擎只是工具重要的是对“游戏循环”的理解——场景管理、组件通信、物理与碰撞、资源加载与释放、UI组织。你在Unity里理解这些概念换到Godot上也就是换一套API的事。反过来用Godot快速做原型练手成本低、反馈快是很适合培养手感的方式。4.3 项目经验一个小Demo的自我修养笔试经验再丰富也替代不了你真正做过一个像样的项目。B站笔试虽然主要看卷面但简历上有没有游戏项目会直接影响后续面试官的问法。我强烈建议每个准备入行的人都自己完整做一个可玩的小游戏。这个项目不用大核心是“完整”。完整的意思是有入口、游戏循环、玩法、UI、音效、打包输出整个链路你都亲手走一遍。哪怕只是极简的2D平台跳跃游戏你也会遇到很多原本以为知道、动手才发现不懂的问题——物体移动为什么抖动、碰撞为什么偶尔穿透、UI自适应为什么在手机上乱套。这些问题每一个都能成为面试中的谈资也是笔试里概念题的最佳注脚。5. 备战校招的实操建议与避坑清单5.1 时间线怎么排我见过太多同学到了秋招才临时看引擎结果笔试遇到Unity生命周期题只能靠蒙。游戏开发方向的学习和纯算法岗不同需要更长的沉淀时间。我推荐的节奏是这样的大二到大三上学期C/C#打底完成一个命令行版的简单游戏大三寒假跟着Unity官方教程完成第一个3D小Demo大三下学期独立做一款完整度更高的作品同时开始刷算法题大三暑期针对目标公司做笔试真题模拟整理引擎和网络高频考点大四秋招集中投递、复盘笔试、准备技术面。这个时间线不一定是唯一解但保证了每个阶段都有作品产出不会最后手忙脚乱。5.2 常见入坑点速查踩坑点具体表现正确做法只刷题不碰项目引擎题全靠背概念面不上手边学引擎边做Demo概念才会落地只做项目不刷题项目经历漂亮算法题写不出来每天固定时间刷高频算法题忽视数学基础旋转矩阵、光照公式一考就懵把向量、矩阵、MVP变换练到默写笔试不检查边界条件循环下标写错整题零分写完人工走查数组边界和循环条件这里说一个只有实际踩过坑才懂的点笔试环境里变量名错一个字母循环边界差一个等于号整道题就可能零分。平时练习时就要培养“写完后人工走查两遍”的习惯尤其是数组下标和循环条件。5.3 笔试卷之外的加分项最后补一个很多人忽略的点笔试只是校招全流程的其中一环卷子答得好不代表万事大吉。技术面时面试官大概率会顺着你简历上的项目和笔试卷里的薄弱点追问。所以每做完一份笔试卷一定要认真复盘把不会的题整理到错题本里。我在那次笔试之后花了整整两天把错题重做了一遍还专门把Unity生命周期和帧同步、状态同步这两个薄弱点补齐了。后来面试时被问到类似问题心里确实有底。实际工作中我也一直在用这套方法——遇到不会的引擎问题先记下来项目做完再回头翻一遍很多当时觉得难的东西第二次看就顺了。这份卷子距今已经过去了好几年但每次看到有人提起B站早年的游戏开发笔试题我都会忍不住再翻一遍自己的复盘笔记。不是怀旧而是这套校招考察方向到现在依然没过时——语言基本功、算法能力、数学与图形学、引擎实战、网络概念依然是游戏开发岗能力模型的主体。如果你正在准备游戏开发校招我希望这篇复盘能帮你少走一些弯路。所有我觉得值得说的经验都写在上面了下一步就是动手写代码、做项目、刷真题。游戏开发这条路没有捷径但每一步都算数。
返回列表