不鸣 引擎

一面

  • 介绍项目经历
  • ECS的优势
  • ECS除了Cache以外的好处
  • 配表相关工作
  • 配表遇到的问题,还有什么可以完善(表间数据引用)
  • C++的sizeof受到哪些影响
  • 空对象的sizeof
  • 虚函数实现原理
  • 析构函数的虚函数
  • 虚函数何时呈现多态
  • 讲讲share_ptr
  • share_ptr除了指针和引用计数器外还有什么成员
  • share_ptr是线程安全的吗
  • 代码测试题目
    • 实现一个成员变量赋值的函数
    • 减少赋值过程的拷贝
  • 反问
    • 岗位是否涉及GamePlay:负责开发引擎的Runtime和插件,本岗位是开发配表插件的

4 二面

  • 问实习项目
  • 如何实现对象池的
  • 都做了哪些配表工作
  • 我提到的Luban插件是如何工作的
  • 如何解决Map嵌套复杂数据类型的场景(然而官方手册上说不支持这个功能)
  • 是否有多线程相关经验
  • share_ptr是线程安全的吗,为什么
  • 代码测试
    • 实现构造函数、拷贝构造、移动构造、拷贝赋值、移动赋值(注意自己赋值自己的情况)
    • 测试这几个构造函数
  • 解释一下Lua元表(因为简历上提过)
  • C++如何与Lua沟通的
  • xlua如何实现C#和Lua沟通的(因为提到了Unity的xlua)
  • 配表相关需求:数据结构嵌套复杂,比如Map的value是不同类型的数据,并要能够平铺在excel表里方便编辑
    • 遇到这个问题时你首先会怎么做(沟通确定需求)
    • 有什么好的解决方法(我举例了V社的“数据驱动类技能”,使用类JSON的结构,但策划需求还是希望能使用excel平铺编辑,方便批量修改)
  • 何时能到岗(年后,大概2-3月,因为要处理毕设)
  • 反问
    • 岗位除了配表插件还有什么工作:大概半年左右完成插件,只会留一两个人负责日常维护升级。之后会转入引擎开发相关工作(包括但不限于动画、AI等),因此还是按照引擎开发的标准招聘问C++内容,而不是问配表插件对应的C#
    • 引擎将来会像Unity和UE一样对外开放吗:是的,但是需要公司内部先研发出两三款热门产品作为证明,提升用户信心后再对外开放。战意使用的是初版引擎,其引擎功能较为特化。目前使用新版引擎的有,升级版战意和FPS项目两个正在开发的项目。

5 三面

  • 简历项目
  • 对游戏引擎内容是否有所了解
  • 一个百万人的服务器,玩家分数会随着对局变动,要求实现前10名的排行榜
  • 4杯水有1杯有毒,有毒的水在30分钟内出现效果,需要几只小鼠才能判断
    • 不限时间:只需要1只,每喝一杯水就等30分钟观察状态
    • 限制时间:需要2只,因为每只鼠都有 死/活 两种状态(信息量为2),而2只就有4种状态。此时我们可以把两只鼠的状态编码成 00/01/10/11 四种状态,再对应到4杯水分别有毒的情况。
  • 15个小球其中1个重量不同,用天平比较几次能找到对应小球
    • 不知球是更轻还是更重:天平比较的结果是 相同/不同,也就是2种状态。类似上一个问题,就是比较4次的信息量为16,才能满足15的条件。(但是没说比较的过程)
    • 知道球是更轻或更重:天平比较的结果是 相同/轻/重,也就是2种状态。这时比较3次的信息量就能达到27,满足15的条件。(但是没说比较的过程)
  • 黑夜中4个人过桥,需要有一人拿着手电筒,每次最多2人一起出发。手电筒只有一个,所以需要拿回对岸再带人过来。四个人的过桥速度分别是1,2,5,10分钟,一起走时速度取最低值。
    • 求4人到对岸用时最少的方法:
      1. 1,2过
      2. 1返回
      3. 5,10过
      4. 2返回
      5. 1,2过
    • 求证时间不可能为16分钟(或15分钟)
  • 反问
    • 面试官是否也是负责配表插件开发:配表插件只是其中一个组的工作内容,还有其他组在做别的工作
    • 岗位新人培训:新人入职会有“导师”带路,一开始先熟悉引擎代码。之后会分配一些非紧急需求作为新人练手项目。

6 四面/HR面

技术

  • 为什么会从客户端转到游戏引擎开发
  • 实习过程中最有挑战性的工作是什么
  • 游戏引擎需要哪些内容
  • 最感兴趣的内容是什么(NPC AI:寻路、状态机状态树)
  • 实现状态机时需要考虑哪些
  • 状态机实现的时候哪些困难的点
  • 策划在使用游戏引擎的时候有哪些痛点需要解决
  • 最近在玩哪些游戏
  • 如何让策划能方便地实现这些功能

诗悦-211本-二面

  1. Lua的table底层原理

hash array

  1. 用过Lua的元方法吗?用在哪些地方?

index newindex add重载+

( index 和 newindex 区别?)(¥¥¥)

访问一个不存在的key 对表中赋值一个不存在的key触发

  1. 图形学渲染管线

CPU GPU CPU:应用阶段 GPU 顶点处理顶点shader 光栅化阶段 片元处理片元shader

  1. ugui有哪些优化方法(¥¥¥)

包括使用动静态 Batch 打包图集 动静分离 对象池

(rebulid 处理)(¥¥)

rebulid 是对于UI发生一些脏标记的行为的时候,标记为dirty的img会触发的重新计算和渲染,rebulid 分为 图像rebulid和布局rebulid

图像rebulid表示在材质之类的脏标记行为时会产生的rebulid

布局rebulid 表示在一些布局比如说transform改变的时候会产生的rebulid

  1. 详细讲一下你刚才说的静态合批和动态合批 (¥)

静态合批和动态合批都是为了减少drawCall的一种处理方式

静态合批就是类似于把地图上不动的物体进行统一合批,利用内存空间换CPU的时间。但是他的缺点是不能去交互这一部分的东西,包括会增加一些内存的使用量。

动态合批就是把一些物体有着相同的texture材质会将这部分一起合批处理,这种处理只能处理一些300顶点以下的mesh ,这部分unity会进行自己的处理,但是这部分处理很不可预测。

  1. 帧同步和状态同步的区别(¥)

帧同步和状态同步俩种不同的游戏网络同步方式。

对于帧同步来说,应该是客户端占主导行为,服务端只要转发这些客户端指令,和客户端检测一下是否有作弊行为,就可以了。

对于状态同步来说,是服务端权威。对于客户端只要给服务端发送一个行为信息就可以了,剩下只要给服务端计算和检测作弊。

帧同步优点是带宽占用低,缺点是容易收到延迟影响,和作弊比较难处理,底层使用UDP,类似与王者荣耀的实时类游戏多用到帧同步。

状态同步优点是每个客户端状态同步方便,但是占用带宽高。

  1. 帧同步一般采用什么方式使得客户端画面一致?(¥)

服务端每一个利用逻辑帧进行帧锁定,广播客户端的行为,并在每一个客户端模拟该行为,确保一致。

帧同步通常采用确定性锁步模拟(Deterministic Lockstep)来保证客户端画面一致。每个客户端在相同的初始状态下,按照相同的输入指令进行模拟,确保每一步的结果一致。缓冲队列和服务器重传是辅助手段,但不是核心机制。

  1. 了解热更新流程吗?(¥¥¥)

热更分为上传和下载

上传过程: 打包热更资源的MD5信息,上传热更资源到热更服务器,上传版本到版本服务器

下载过程:检测版本服务器是否一致,不一致在热更服务器下载md5文件,对比热更目录后,把不一致的md5码标记的热更资源区下载。

运行游戏:优先加载热更目录,后再母包加载。

腾讯ieg魔方-211本-二面

—八股+项目阶段+算法阶段—

  1. 分别介绍下c++和c#里面的struct和class的区别(背了一通)

    C++访问模式的区别st是private class 是pubilc

  2. 说一下c++里面堆和栈的区别(背了一通)

    堆,栈

    堆是由程序员分配的malloc free区,内存区域大(4G) 分配效率较低,可能产生内存碎片,地址是低向上

    栈是有OS分配的区域,自动分配 内存区域小(1M)分配效率高,为函数和局部变量存储分配的内存,地址是由高向低

  3. c++里面除了程序员手动malloc new delete或者free掉 还有什么其他的内存管理方式吗(不太清楚了 随便回答了智能指针啥的)

  4. 你说到智能指针 能介绍下吗(说了四种智能指针 auto_ptr被弃用了 shared_ptr unique_ptr weak_ptr)

    共享指针 多个shared_ptr可以指向相同的对象,采用引用计数机制。当最后一个引用销毁时,释放内存空间。
    独占指针 保证同一时间段内只有一个unique_ptr能指向该对象,可通过move操作来传递unique_ptr。
    弱指针 weak_ptr用来解决shared_ptr相互引用时的死锁问题,是对对象的一种弱引用,不会增加对象的引用计数。
  5. 说一下这些智能指针的底层 可以自己手搓智能指针吗(回答了shared_ptr的引用计数机制以及和weak_ptr的结合 unique_ptr把拷贝构造和赋值构造给=delete啥的)

    ???

  6. 你说到map 那map底层是什么(回答红黑树)介绍下红黑树的性质和特征(大致介绍了下)

    红黑树: 1.每个节点非红即黑 2. 根节点是黑色的 3. 一个节点是红色,子节点是黑色的 4.任意一个节点到树枝的路径黑色节点是数量必须相同。

  7. 你知道红黑树为什么要设计成这样子吗 (回答 自平衡 中序遍历有序 插入删除logn 啥的)

    最后一点导致了每条path都不会多出俩倍以上。适合频繁插入查找

  8. 协程 线程 进程区别是什么(常规背诵 多提了一嘴线程切换不会切换地址空间 tlb缓存不会变化 进程会切换地址空间 tlb会变化)

    协程 用户态的轻量级线程 程序公共资源通信
    线程 CPU调度最小单位 OS调度 共享内存 PV操作互斥锁
    进程 操作系统资源最小调度单位 IPC 进程内通信,OS通信
  9. 线程间怎么样通信的?(互斥锁 信号量 举了下c#中lock和mutex的例子以及semaphore的例子)

  10. 你在项目中实现过多进程或者多线程吗(回答实现过多线程)

  11. 你项目中提到你的服务器使用c#编写的 服务器是自己写的吗 服务器逻辑是什么(回答 服务器参照了网上的教程 大概就是服务器和客户端建立的连接用一个token来进行标记和通信 用一个token池来集中管理)

    RPC模型封装一个协议id(token), 每个连接都放在池子里面,利用id去调用

  12. 你提到了帧同步 介绍下(介绍了下帧同步)

  13. 帧同步有时候不会同步特别准确 该如何解决?(定点数 冗余包 客户端预测 回滚 校正啥的 之后面试官和我补充了一些知识点 因为他们组是做帧同步这块儿的)