2022 TDS游戏工作室笔试

First Post:

Last Update:

Word Count:
4.4k

Read Time:
15 min

2022 TDS游戏工作室笔试

以下是我在2022 TDS游戏工作室的填写的笔试内容,由于个人某些原因没去参加面试。

1 请简述缓存机制在计算机中的应用。

  1. 比如CPU寄存器与内存之间的数据传输,寄存器与内存的传输速率都有着较大的差距,为了避免在处理数据时,cpu等待内存传输过来的时间,在寄存器与内存之间加了缓存器,采用缓存方式来降低等待数据的时间.
    把最常用的数据放在缓存里,CPU读取缓存里的数据就可以了.
  2. 游戏里也会有,游戏再加载场景的时候,会将场景资源数据读到内存的缓存里中,需要的资源的时候直接从缓存中读取就可以,无需再从磁盘中读取,提高了访问速度.
  3. 在服务端开发的时候,接收一个文件时,并不是收到数据就将其数据写入到文件里,若在网络比较差的情况,会造成多次使用文件IO写入数据到磁盘,对其开销比较大,为了降低CPU开销,开辟一定范围的内存来对文件数据进行缓存,达到一定数量再将其写入到文件中.在服务端开发中,类似的还有日志系统,打日志的时候并不是实时的,采用缓存方式降低开销.在c语言中printf,scanf,fprintf,fscanf,puts函数里都有相关缓存,里面有FILE结构体,该结构体中就包含了文件IO的缓冲区,目的是为了降低CPU开销.
  4. 在TCP底层协议中也包含了缓存机制,比如滑动窗口移动依赖于数据的缓存,为了让数据超时时重发,丢包时重发,一次能够发送较大的数据包.

总结: 1. 提高访问速度, 2. 降低CPU消耗 3. 安全验证

2 请简述UDP和TCP的差别。

  1. 包头长度差别, 基于IPV4/IPV6上的 UDP包头首部长占8字节, TCP包头首部长占20字节
  2. tcp需要建立连接之后才能发送数据,udp不需要建立连接即可直接发送数据.
  3. 可靠性差别,tcp是一种可靠协议,建立连接后断开连接前传输数据丢包率几乎为0, udp是一种不可靠协议,可能会出现丢包现象.
  4. 速度差别, 由于udp包头相对比tcp短,且udp不需要建立连接,且有很多的验证机制udp没有,udp的传输速度相对较快.
  5. UDP可在局域网实现广播功能(相当于又充当服务端,有充当客户端), TCP只能采用服务中转才能实现广播.
  6. UDP可以实现打洞功能,TCP不能. 打洞技术在IM技术中尤为常见, 比如QQ的离线文件发送,传输的数据是不需要经过服务端中转的.

3 系统页面文件

系统页面文件也就是虚拟内存所缓存数据的文件,当物理内存容量不够用时,可以创建一个虚拟内存来增大内存容量,来实现装载更大的程序,唯一的缺点就是,装载程序置虚拟内存中时比较慢。

4 系统页面向对象

面向对象(OOP)是一种编程思想,把我们要实现的东西想看作为对象,该对象又可以由多个对象组成.
构建对象的特性一般有封装,继承,多态.
该对象可以开放功能(该对象的用途) [封装],
可以基于之前的对象迭代增加新功能创建出新对象[继承] 且可以修改之前有的部分功能[多态].

比如生产一辆汽车,我们可以将汽车看做一个大的对象,而我在生产汽车前我们需要完成生产方案.
若有个汽车制造工厂参考了我们的汽车生产方案,制作出适合他们工厂新的方案 这个过程叫做继承.
方案中所涉及的一些配件,只需说明是什么规格的配件, 配件上的技术不公布,只告诉你是什么,怎么用,这种情况可以称做封装.
汽车制造商参考了我们的生产方案,且对我们原来生产方案中做了某些方案覆盖实现修改,可以覆盖原来的部分方案性质叫做多态.

5 系统页请简述C#中可空类型的使用方法与存在意义。

简单使用方法:
Nullable i = new Nullable(0); // 声明一个可空int类型的变量i, 且赋初始值为0
int? i2; // 声明一个可空int类型的变量空变量i2,初始值为null

存在的意义:
1. 可以定义一个未被赋值的变量
2. 可以判断值类型对象是否被赋值.

6 系统页请简述C#中流的操作要点。

流用于对IO处理的一种缓存机制,也是对IO操作细节的一个封装, 如文件操作,网络通信,内部通信,IO设备通信等.
一般来说,流的操作
流读取:操作是从流到数据结构的传输
流写入:该操作时从数据结构到流的传输
流查找修改:对流内的当前位置进行查询与修改
流一般有内存流 MemoryStream,缓冲流BufferedStream,网络流 NetWorkStream, 文件流 FileStream,文本流 StreamWriter,字符串流 StringWriter等,其用法都是基本类似的.

7 系统页列举至少三种排序方法,并简述每种方法的实现逻辑。

有冒泡, 选择, 插入, 归并排序, 快速排序,还有其他的等等.

冒泡排序:
若长度为n的数组,从左往右两两比较,若左边大于(小于)右边,则进行交换,这为一轮,多进行n - 2次轮即可完成排序.

选择排序:
1. 将数组分成已排序区与待排序区
2. 在待排序区域找最大值或最小值放在已排序区.
3. 依次进行2步骤即可完成排序.

插入排序:
1. 将数组分成已排序区与待排序区
2. 从待排序区取下第一个数与已排序区从后依次数比较(若没有数直接放),找到合适的位置放入,(放入时需要进行数据移动).
3. 多次进行2,即可实现排序.

归并排序:
把长度为n的输入序列分成两个长度为n/2的子序列;
对这两个子序列分别采用归并排序;
将两个排序好的子序列合并成一个最终的排序序列。

快速排序:
首先设定一个分界值,通过该分界值将数组分成左右两部分
将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值
然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理
重复上述过程,通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了

8 系统页依据特点比较栈和队列。举例说明它们各自的实践运用。

​ 栈结构是先进后出,队列是先进先出.
​ 堆栈运用
​ 1. 比如在计算机中,函数的调用约定,局部变量的储存这些都是采用堆栈结构储存的.函数的汇编指令 call和ret, call A 等价于 push 下一条指令地址 (将下一条指令地址压入), jmp到目标地址A,ret 相当于 pop eip(将栈顶数据弹出来).

    2. 函数的递归调用也可以采用堆栈数据结构来实现.
    
    队列运用
    1. 队列的话在服务端开发比较常用,比如消息系统可以采用队列来实现,这样不会影响到消息数据的先后顺序.
    2. 请求缓冲区, 有时候在后台中,数据库可能需要查询很久,若服务器是异步的,我们可以将请求放在队列中进行等待.

9 对于会出现大量的、重复的、短暂的使用某一种对象的操作,我们通常使用哪一种设计模式来减少该对象在主循环生成时所带来的开销?

​ 单例模式

10 假设你需要让游戏支持成就系统,但同时不希望成就计算内嵌在游戏主代码之中,你会采用哪一种设计模式来实现此功能?

工厂模式

11 请简述模型和贴图的本质。

模型是采用3d建模软件构建的,是虚拟物体形体的表现.
贴图是基于模型之上表达更丰富的元素,比如模型的颜色,阴影.

12 必填请详述FixedUpdate、Update与LateUpdate之间的区别和Time.deltaTime与Time.fixedDeltaTime的区别。

FixedUpdate是以恒定帧率调用的,以恒定的时间间隔进行调用
Update是每一帧调用一次,会受到对象渲染的影响,可能时间间隔会发送变化.
LateUpdate是调用完Update之后再去调用LateUpdate

13 Unity中,GameObject、Transform和MonoBehaviour之间的关系是什么?

GameObject是Unity最基本的对象, Transform是GameObject的一个基本组件,但又是Transform的一个特殊组件,该组建包含了父子对象的与子对象的层级结构
MonoBehaviour是Unity中脚本的基类,脚本是GameObject上的一个组件,当一个GameObject挂上脚本之后,创建该对象,就会触发该脚本运行.脚本会先调用重写MonoBehaviour中的
Awake函数, 在实例化所有GameObject组件后,再去播放游戏帧,才会调用脚本中的Start等等一系列其他函数.

14 请简述Unity中Gizmos的使用方法。

Gizmos是用于场景可视化调试用的,在Unity Sence面板右上方有Gizmos一个图标,可以打开或关闭,比如打开时,可以看到灯光,摄像机,用于方便我们确定位置,关闭时就看不到了.
Gizmos还提供了一些列可操作函数,更改默认的一些显示属性.

在继承于MonoBehaviour类中,重写OnDrawGizmos与OnDrawGizmosSelected即可
OnDrawGizmos是不运行游戏都会自动不断调用
OnDrawGizmosSelected只有选择该对象后才能调用该函数.
Gizmos提供了一些API函数如下
Gizmos.DrawRay //绘制射线
Gizmos.DrawCube // 绘制方体
还有其他等等一系列函数可以用,根据gizmos提供的绘制函数,将代码放在OnDrawGizmos或OnDrawGizmosSelected就可以了

15 请简述ScriptableObject在游戏制作中可能的应用。

让游戏永久性的保存数据,将数据储存在资源文件中
1. 有时候为了我们开发人员的一个开发,有一些游戏数据是需要保存的,但我们定义的一些全局变量来储存游戏数据,游戏重新运行数据就没有了,为了保存游戏数据,我们可以通过
ScriptableObject来储存
2. 场景数据对象,在场景进行切换时,我们可以通过该对象很方便的实现数据共享,每个场景都可以更改或查看数据.

16 一些游戏(参考:《 Super Hot 》、《猎天使魔女》、《GTA5》)中“子弹时间”的存在意义是什么?谈谈你如何用程序实现,并怎样优化其效果和提高玩家体验。

​ 让玩家体验另一种感觉,时间变缓慢,能够突出动作的精彩部分,带来震撼视觉效果。
​ 可通过调整TimeScale和Time.fixedDeltaTime的值来实现速度变慢的效果。
​ 不同设备可能有着不同的性能,如果性能好,帧率比较高,可以通过MaximumParticleTimestep来限制播放的速率。如果性能比较拉胯,可以调整
​ MaximumAllowedTimestep来限制最大时间间隔,FixedUpdate函数每帧时间不会超过该值,保证程序正常模拟物理效果。

void Update()
{
    if (Input.GetButtonDown("Fire1"))
    {
        if (Time.timeScale == 1.0f)
            Time.timeScale = 0.7f;
        else
            Time.timeScale = 1.0f;
        Time.fixedDeltaTime = this.fixedDeltaTime * Time.timeScale;
    }
}
https://docs.unity3d.com/Manual/class-TimeManager.html

17 如果你要使用Unity引擎制作一款卡牌游戏(参考:《炉石传说》、《杀戮尖塔》),请简述一下你的实现思路。

简单策划如下:
首先先定义英雄属性,职业,生命,护甲和技能, 物理攻击力,魔法攻击力,防御力。
定义一共通用的关卡模板,使用同一个场景。
每一关只是挑战的英雄不同,还有剧情不同,通过数据来实现控制每一关的不同。
定义不同的关卡数据,剧情数据。
在关卡中战斗中,按照先后顺序进行攻击,玩家根据自己选择英雄的技能进行攻击,自己的英雄死亡失败,敌方的英雄死亡胜利。

服务端大致思路:
    游戏数据储存在后台,需要有服务端,卡牌类游戏实时性不是那么强,那么可以采用tcp协议加一个epoll非阻塞反应堆来架构游戏后台。
    为了游戏的安全性,游戏数据传输需要进行私有协议加密,让游戏数据方便管理,还需要单独开发管理后台。
    数据储存的话就采用mysql,缓存可以采用redis或者mongoDB。需要单独开发,网关服务器,登录服务,主服务器,cdn服务器,房间服务器。

    网关服务器,主要负责处理客户端获取各个服务器ip地址的请求,发送配置文件的服务器。
    cdn服务器负责热更新资源下载,架设个nginx即可。
    登录服务器,主要是账号登录,分发服务器通用授权的cookie,可采用单点登录实现思路。
    房间服务器,每一关战斗处理的服务器,负责按照游戏规则实现机器人与玩家战斗数据同步与作弊监测。按照给定的游戏规则,与玩家进行战斗模拟,且战斗涉及的变量值会在该服务器里完成计算,并且设定战斗结束条件。
    主服务器,与各各服务器之间数据库之间相联系。储存游戏规则,英雄,玩家,关卡数据等,还负责处理玩家交互请求,后台管理请求等。
    
客户端大致思路:
    进入游戏时,访问网关服务器,获取各个服务器的ip地址。
    校验当前版本与cdn服务器中资源版本是否对应,若当前版本比较旧,就从cdn服务器下载资源更新版本。
    账号登录,登录后获得授权cookie值,后期与服务器交互需要加上该值。
    从服务端获取各个英雄的属性,还有关卡信息,玩家数据,将其数据通过指定的样式渲染出来。
    进入战斗房间,向服务端申请房间服务器,服务端回馈ip地址,后期战斗就通过该服务器进行数据传输。
    玩家每点击一个技能,都会向房间服务器发送释放技能请求,战斗血量值加减在服务端实现,客户端只对数据进行渲染成画面。
    处理游戏战斗结束画面,对服务端返回的得分或者经验值进行增加渲染。

18 一个游戏通常应该由哪些职位合作完成?简述各个职位(重点是程序)的作用。

策划员,美工,程序员,管理员。
​ 策划员:负责对游戏内容(数值,剧情,文案,运营)进行策划。
​ 美工:按照策划员的策划进行模或者制作出游戏UI。
​ 程序员:根据策划员提供的策划与美工提供的游戏素材采用编程创造出相应的游戏软件,其中测试员,运维人员,都可以包含在其中。
​ 管理员:负责考勤,管理各个职位的配合,还有法律相关问题。

19 游戏开发中的程序大概可分为哪些方面?描述一下你未来想要从事方面的具体工作。

业务型和研究型吧。
业务型,会使用常规引擎根据业务需求开发出满足需求的游戏,一般是使用现成的库来实现相应的需求。
研究型,对游戏引擎进行深入研究,研发相关实用的引擎插件,或者研发出属于自己公司内部的引擎,对游戏物理进行研究,模拟出更好的物理效果,还有人工智能寻路,自动战斗。画面优化,性能优化等等。

打赏点小钱
支付宝 | Alipay
微信 | WeChat