☰
B站游戏开发笔试卷深度复盘:从C++到Unity的考点解析
2026/10/31 8:08:31 网站建设 项目流程

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(vector<vector<int>>& grid, pair<int,int> start, pair<int,int> end) { int rows = grid.size(), cols = grid[0].size(); vector<vector<int>> dist(rows, vector<int>(cols, -1)); queue<pair<int,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》的重点章节过一遍,尤其是指针、引用、内存管理和STL;C#则以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站早年的游戏开发笔试题,我都会忍不住再翻一遍自己的复盘笔记。不是怀旧,而是这套校招考察方向到现在依然没过时——语言基本功、算法能力、数学与图形学、引擎实战、网络概念,依然是游戏开发岗能力模型的主体。

如果你正在准备游戏开发校招,我希望这篇复盘能帮你少走一些弯路。所有我觉得值得说的经验都写在上面了,下一步就是动手写代码、做项目、刷真题。游戏开发这条路没有捷径,但每一步都算数。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询