求职日记:面试准备
基础知识大串讲
这里会记录可能问到的基础知识,也是对我所学的一个复习回顾。
C#相关
委托和事件
- 委托和事件是什么?使用事件对比直接使用函数调用有什么优势?
- 委托和事件:
- 委托和事件是存有方法引用的类型,他们的区别在于事件是委托的安全包裹,只能在声明它的类内部执行
Invoke();外部仅可+=、-=函数。
- 委托和事件是存有方法引用的类型,他们的区别在于事件是委托的安全包裹,只能在声明它的类内部执行
- 优势:
- 降低耦合度。使用事件实际上是设计模式中观察者模式的体现,发布者不必关注订阅者的逻辑行为,订阅者在换逻辑时也只需注意加减函数,不必修改大量逻辑。
- 访问更安全。外部不可
Invoke() - 支持一对一广播,触发式全部自动执行。
泛型
- 泛型的作用,举例说明。
- 泛型的作用:
- 复用代码逻辑
- 避免装箱拆箱
- 例子:
List<T>
接口和抽象类
- 接口和抽象类的核心区别?
- 关键字:接口
interface,抽象类abstract class - 成员:接口默认无字段、不能有实例变量;抽象类可以有字段、属性、构造函数
- 继承:一个类只能继承一个抽象类,但是可以实现多个接口
- 设计:接口强调能做什么、抽象类强调是什么
Unity相关
生命周期
MonoBehaviour的完整生命周期,说说Awake()和Start()的区别,Update()、FixedUpdate()和LateUpdate的区别。
- 生命周期:
Awake -> OnEnable -> Start -> FixedUpdate -> Update -> LateUpdate -> OnDisable -> OnDestory Awake()和Start()的区别:Awake():在物体被实例化时执行,即使脚本失活也能执行。用于初始化赋值。所有物体的Awake()执行完后,才会开始执行Start()。Start():在Awake()之后,Update()第一帧开始前执行,必须当脚本被激活时才能执行。常用于需要等待其他数据的逻辑上。
Update()和FixedUpdate()和LateUpdate()的区别:Update():每帧执行,帧间隔不固定。用于处理普通业务逻辑。比如物体移动、摄像机移动FixedUpdate():按照固定时间间隔执行,不受帧率影响。用于处理与物理相关的逻辑。LateUpdate():所有Update()执行完毕后才运行。常用于跟随逻辑(相机跟随角色、挂件跟随主体),避免Update物体移动完相机滞后错位。
方向向量和位置向量
- 方向向量和位置向量的区别
- 方向向量:只关心方向,不关心起点终点。可以用两点坐标相减得到。
- 位置向量:是从世界原点指向空间某物体位置的向量,用来记录一个点在哪。是物体的
transform.position
工程文件夹
常见的工程文件夹及作用
- 常见的工程文件夹有哪些?分别有什么作用?
- Assets:工程资源文件夹,存放美术资源、预制体、脚本等等
- ProjectSettings:工程设置文件夹,有工程的设置信息
- Packages:包管理器的设置信息
- Library:库文件夹
- Logs:日志文件夹
- Resources:资源文件夹
- StreamingAssets:流动资源文件夹
- Editor:编辑器文件夹,写编辑器扩展
编辑器扩展实例
- 写过哪些编辑器扩展?有什么作用?
在做一个《宝石填色》的小游戏时,我写了一个解析图片生成为棋盘的编辑器扩展:

首先我们要知道,Editor文件夹下的东西在打包时都不会被Unity打包出去,因此,我们可以给整个脚本的头部和尾部加上条件编译预处理器指令:#if #endif,编译前处理,不满足直接从源码删掉。
1 | [] |
这个编辑器特性就是告诉Unity当检视目标组件时,不用系统默认的Inspector,改用这个类来绘制面板。
其中,目标组件类型可以用typeof(类名)求得。
然后将这个类中Inspector的某一个按钮和LevelImageParser自己写的解析图片颜色转为棋盘的类关联即可实现这个功能。
我有一个类LevelImageParser,它的结构如下:
struct PalleteSample:(结构体)颜色样本- int id
- Color baseColor
- Color gemColor
它的作用是告诉解析器,哪个颜色对应哪个宝石id
int[] Parse(...):将图片解析为棋盘的核心方法- 参数:
Texture 2D source、棋盘宽高、int pixelsPerCell每格多少像素、IReadOnlyList<PaletteSample> palette - 返回值:一个长度为
width * height的int[] - 逻辑:
- 参数:
1 | int pixelX = Mathf.Clamp(x * pixelsPerCell + pixelsPerCell / 2, 0, source.width - 1); |
意思就是:
- 每个格子都取“中心点”
- 因为图像坐标和 Unity 的格子坐标上下方向相反,所以
y要翻转 - 再对中心点附近做一次平均采样,减少噪点影响
然后:
1 | if (IsEmptyColor(sampledColor)) |
如果这格是透明或空白,就记成空位。
如果不是,就拿采样颜色去和调色板比,找最近的宝石 id。
资源优化
移动端需要注意的坑
- 移动端输入处理需要注意哪些坑?
- 触摸点击事件有300ms延时
- 多点冲突、滑动和点击事件冲突
- 手指越界,手指移出按钮后要正确结束输入
- 多分辨率适配
- 坐标转换,屏幕坐标要转为游戏坐标
资源优化的方法
- 资源优化有哪些方法?
- 打图集减少
drawcall - 压缩图片纹理
- 不用的物体及时销毁
- 对于需要频繁创建销毁的物体,采用对象池复用
- 避免每帧进行大量计算
- 如果游戏卡帧、掉帧,检查思路是什么?
- 看Unity性能面板,检查
drawcall - 看帧更新逻辑,是否有大量循环、实例化
- 检查资源:图片过大、没打图集
- 检查内存:是否有对象没有销毁,频繁GC
Playable Ads 试玩广告
Playable可玩广告的定义
- 什么是Playable可玩广告?它与普通小游戏有什么区别?
Playable可玩广告就是交互式试玩广告,用户不用下载APP,直接在广告位体验精简玩法,完成后跳转下载引导页。
它与普通小游戏的区别是:
- 时长严格限制
- 性能要求极高
- 目标是广告转化,不是完整的游戏体验
- 生命周期受广告SDK管控,有暂停、销毁、回调,不能常驻后台
游戏状态机与Playable
- 解释游戏状态机是什么,举一个在Playable广告中的使用场景。
游戏状态机可以理解为把各个状态封装成一个个不同的类,状态机持有当前的状态,当条件改变时,切换状态。
Playable中可能有加载状态、教程引导状态、游玩状态、胜利失败状态、引导下载状态。
GIT相关
- 简单说下使用Git的合作流程,遇到冲突时怎么解决?
- 首次拿到项目,克隆仓库:
git clone - 开发新功能,创建自己的分支:
git checkout -b feature/功能描述 - 本地写代码,提交到本地仓库:
- 把改动加到暂存区:
git add . - 提交到本地仓库,写备注:
git commit -m ""
- 把改动加到暂存区:
- 推送本地分支到远程仓库:
git push origin feature/功能描述 - 发送合并请求PR(Pull Request):在GitHub上新建PR,请求把
feature/功能描述合并到main主分支,再交给同事审评 - 审评通过,合并分支:
main中有我写的代码 - 所有人同步最新主分支
git checkout maingit pull origin main
当遇到冲突时找到冲突标记,人工选择/合并两边代码逻辑。git add、git commit完成冲突提交。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 MeiMeiBlog!






