MIL11——模拟面试题

C#

  1. 文件中保存了文本信息,但是打开后却是乱码,一般是什么原因造成的?
  2. C# 中 new​ 关键字的作用(至少说出3种)
  3. 同步方法和异步方法的区别是什么?异步编程是什么意思?对于我们来说,什么时候需要使用异步编程?(至少说出3种)
  4. 回调函数指什么?一般在什么时候使用?(至少说出3种使用场景)
  5. 如何用一个 int 变量,记录 32 种状态?(注意:状态可以并存)

Unity

  1. 请解释 Unity 中的 Prefab 是什么,以及它在游戏开发中的作用是什么?
  2. 在 Unity 中,什么是 Shader?它有什么作用,以及如何编写一个基本的 Shader?
  3. 在 Unity 中,什么是常见的性能优化技巧?请举例说明。
  4. 在 Unity 中,什么是协程(Coroutine)?它有什么作用,以及如何使用它?
  5. 解释一下 Unity 中的渲染管线(Rendering Pipeline)是什么,如何使用它,并举例说明它在游戏开发中的应用场景。

答案

C#

  1. 文件中保存了文本信息,但是打开后却是乱码,一般是什么原因造成的?

    序列化和反序列化字符串时使用的编码格式不统一

  2. C# 中 new​ 关键字的作用(至少说出 3 种)

    1. 创建新对象
    2. 子类函数声明时加上 new​ 关键字,可以隐藏掉父类方法
    3. 泛型约束中使用 new​ 关键词,表示需要无参构造
  3. 同步方法和异步方法的区别是什么?异步编程是什么意思?对于我们来说,什么时候需要使用异步编程?(至少说出3种)

    • 同步方法: 当一个方法被调用时,调用者需要等待该方法执行完毕后返回才能继续执行

    • 异步方法: 当一个方法被调用时立即返回,并获取一个线程执行该方法内部的逻辑,调用者不用等待该方法执行完毕

    • 异步编程: 在日常开发时把一些不需要立即得到结果且耗时的逻辑设置为异步执行,
      这样可以提高程序的运行效率,避免由于复杂逻辑带来的的线程阻塞

    • 什么时候需要使用异步编程:

      1. 复杂逻辑计算时,比如寻路算法等
      2. 网络下载、网络通讯
      3. 资源加载时

      等等

  4. 回调函数指什么?一般在什么时候使用?(至少说出3种使用场景)

    回调函数指在程序设计中,将一个函数作为参数传递给另一个函数,并在另一个函数执行完毕后被调用的函数,在 C# 中,一般以委托形式出现

    什么时候使用:

    1. 异步编程:异步逻辑执行完毕后,再执行回调函数
    2. 事件中心
    3. UI 界面中的空间逻辑回调,比如按钮点击

    等等

  5. 如何用一个 int 变量,记录 32 种状态?(注意:状态可以并存)

    int​ 在 C# 中占4个字节,共32位,我们可以按位记录状态,每一位代表一个状态,1​ 为存在,0​ 为不存在

Unity

  1. 请解释 Unity 中的 Prefab 是什么,以及它在游戏开发中的作用是什么?

    在 Unity 中,Prefab 是一种游戏对象的预制件或者模板。
    它允许你在编辑器中创建一个游戏对象,并将其保存为Prefab,以便在需要时可以实例化多个相同的对象。
    当你在场景中使用一个 Prefab 实例时,它将保留与原始 Prefab 相同的组件、属性和位置,使得你可以轻松地创建和管理大量相似的游戏对象。

    Prefab 在游戏开发中的作用非常重要,因为它们允许你创建可重用的游戏对象,并且可以在开发过程中快速迭代和修改。
    例如,当你需要在游戏中生成大量相似的敌人时,使用一个敌人 Prefab 可以使得你仅需创建和修改一个敌人对象,而不必重复编写和调整代码。
    此外,Prefab 还允许你在编辑器中预览和调整游戏对象的属性和组件,使得你可以快速地进行修改和测试,从而加快开发进程。

  2. 在 Unity 中,什么是 Shader?它有什么作用,以及如何编写一个基本的 Shader?

    在 Unity 中,Shader是一种用于定义渲染对象的程序。它描述了对象的外观、材质和光照效果。
    在渲染场景时,每个对象都会使用其对应的 Shader 来生成像素颜色,并最终呈现到屏幕上。
    在 Unity 中,可以使用着色器语言(ShaderLab)和高级着色器语言(HLSL)编写自定义的 Shader。

    Shader 在游戏开发中具有非常重要的作用。它们控制了游戏对象的外观和性能,
    并且可以根据需要创建各种各样的视觉效果,比如透明度、反射、阴影、发光等等。
    使用自定义 Shader 还可以实现一些特定的效果,例如水波纹、烟雾、火焰等等。

  3. 在 Unity 中,什么是常见的性能优化技巧?请举例说明。

    • 从内存的角度来说

      • 尽量要占用少

        • 使用对象池:对象池是一种常见的技术,用于缓存和重复使用游戏对象,而不是频繁地创建和销毁它们。
          使用对象池可以减少内存分配和垃圾回收的开销,从而提高游戏性能。
        • 减少资源占用:在开发过程中,应该尽量避免使用过多的高分辨率纹理和复杂的模型。
          可以使用纹理压缩、减少纹理尺寸、使用轻量级的模型等方式来减小资源占用。
        • 及时销毁不再使用的对象:当游戏中不再需要使用某些对象时,应该及时销毁它们,以释放它们占用的内存。
          尤其是一些长时间存在的对象,如粒子系统、音频和视频资源等,都应该及时销毁。
        • 使用异步加载:如果游戏中需要加载大量的资源,可以使用异步加载技术。
          异步加载可以减少游戏卡顿和内存占用,从而提高游戏性能。
          可以使用 Unity 提供的异步加载 API 或者自定义异步加载方式来实现异步加载。
        • 使用资源打包:在打包游戏时,可以使用资源打包技术来减少游戏的内存占用。
          资源打包可以将多个资源打包成一个单独的文件,从而减小游戏的内存占用。
          可以使用 Unity 提供的 AssetBundle 功能或者自定义打包方式来实现资源打包。
      • 尽量要减少 GC

    • 从 CPU/GPU 的角度来说

      • 减少 Draw Call:在 Unity 中,每次渲染一个物体都会使用一个 Draw Call。过多的Draw Call会导致渲染性能下降,因此应该尽量减少它们的数量。可以通过合并网格、使用物体批处理和减少物体数量等方式来减少Draw Call。
      • 使用级别 LOD:如果场景中有大量的物体,可以使用级别 LOD 技术来优化性能。
        通过在远离玩家的位置使用低分辨率的网格,可以降低渲染开销,提高性能。
      • 合理使用资源:在开发过程中,应该尽量避免使用过多的高分辨率纹理和复杂的模型。
        可以使用纹理压缩、减少纹理尺寸、使用轻量级的模型等方式来减小资源占用。
      • 使用光照贴图:在游戏中,光照是非常重要的,但是使用动态光照会带来很大的渲染开销。
        因此,可以使用光照贴图来减少动态光照的数量。光照贴图可以在编辑器中生成,并且可以有效地提高游戏的性能。
      • 使用对象池:对象池是一种常见的技术,用于缓存和重复使用游戏对象,而不是频繁地创建和销毁它们。
        使用对象池可以减少内存分配和垃圾回收的开销,从而提高游戏性能。
  4. 在 Unity 中,什么是协程(Coroutine)?它有什么作用,以及如何使用它?

    协程(Coroutine)是一种在 Unity 中常用的编程技术,用于在运行时控制代码的执行顺序。
    协程可以将代码执行分为多个阶段,可以在其中暂停和恢复代码执行,从而实现异步执行和任务管理等功能。

    协程的主要作用包括:

    • 延迟执行:协程可以延迟执行某个任务,从而在指定时间后执行相应的操作。
    • 异步执行:协程可以在后台执行任务,从而避免卡顿和阻塞主线程。
    • 任务管理:协程可以管理多个任务,从而实现更灵活和可控的代码执行顺序。
  5. 解释一下 Unity 中的渲染管线(Rendering Pipeline)是什么,如何使用它,并举例说明它在游戏开发中的应用场景。

    • 几何图形的准备:将场景中的几何图形转换为渲染引擎可以理解的形式,例如将3D模型转换为网格数据(Mesh)和材质信息。
    • 光照计算:计算场景中每个几何图形的光照效果,包括直接光照和间接光照。
    • 视点变换:根据摄像机的位置和方向将场景中的几何图形转换为摄像机的视图空间(View Space)坐标系下的形式。
    • 投影变换:将摄像机的视图空间坐标系下的几何图形转换为投影坐标系下的形式。
    • 图像空间计算:将投影坐标系下的几何图形转换为屏幕上的像素坐标。
    • 着色:根据材质信息和光照信息对几何图形进行着色,计算每个像素的颜色值。
    • 合成:将所有的像素颜色值按照一定的顺序合成为最终的图像,输出到屏幕上。