找回密码
 立即注册
查看: 290|回复: 0

Unity游戏开发面试问题整理(一)

[复制链接]
发表于 2023-3-27 09:32 | 显示全部楼层 |阅读模式
下面问题均是个人开发和面试过程中遇到的一些常见问题,致力于深入研究和剖析,非面经题库。但所有问题均来自个人笔记,非标准答案,对问题研究有深有浅,如有错误请指出
1. 什么是GC?关于Unity的GC要注意些什么?


  • Garbage Colloect,垃圾回收,是一种内存管理技术。C#能够自动分配和回收内存。回收分配的内存的过程就叫做GC。
  • 对于Unity来说,GC由MONO VM或者IL2CPP来完成。存在以下问题
  • 不分代GC。每次都是全量遍历,单次GC耗时较长
  • 基于MarkSweep的。因为在回收后不会紧缩内存,会有内存碎片问题
  • 非精确的GC。不能准确识别内存地址,因此GC时可能会把一些数值类型识别为地址。
  • 因为以上问题,Unity GC效率很低,是个坑。Unity开发中几乎任何高频GC代码都会成为性能瓶颈,写代码时应注意代码是否会触发GC、触发GC的频率、是否分配后可以缓存等。
2. 叙述下Mono的生命周期


  •   https://docs.unity3d.com/cn/2020.3/Manual/ExecutionOrder.html
3. 叙述下Unity里协程的用法、原理和问题


  • 协程是UnityMono生命周期中一种特殊的更新函数,遇到对应的yield语句则会暂停,并在指定的时机恢复执行。
  • 用法:
  • 定义一个返回IEnumerator的函数,并使用StartCoroutine启动协程;
  • 定义一个返回async Task的函数,并使用StartCoroutine启动协程;
  • 协程本身可以用来解决一些分帧、定时、异步等问题。并且使用时机可定制、较为灵活
  • 原理:   协程的实现基于迭代器、Mono内部状态机和yield语法糖。在协程启动后遇到yield就会返回迭代器并保存当前状态。当协程恢复执行时(这个时机固定在某一个生命周期中,保序),从之前的状态继续执行。
  • 存在的问题:
  • 协程可能会导致代码难以理解和维护,特别是当使用复杂的协程链时。
  • 协程可能会导致性能问题,特别是当使用大量协程时。每个协程都需要在状态机中占用一些内存,并且在执行时需要进行状态转换和保存。
  • 协程可能会导致崩溃和错误,特别是当使用不正确的协程操作时。例如,当在协程中使用异步操作时,需要小心避免竞态条件和死锁。
  • 协程并不是一个新的线程,仍然跑在Unity的主线程上,因为缓存、状态切换的问题,总耗时比一次执行完更高
4. 叙述下什么是AssetBundle?并聊一下其原理和用法


  • 介绍及其原理:
  • Unity AssetBundle 是一种用于存储、管理和重用 Unity 资源的文件格式和机制。开发者可以将游戏资源打包成一个个独立的文件,利用好AB可以实现资源的动态加载和热更
  • AB包可以在游戏运行时动态加载和卸载。AssetBundle 打包的资源可以是场景、模型、纹理、声音等等。在打包 AssetBundle 时,Unity 会将资源压缩成二进制格式,并生成对应的元数据文件。元数据文件中存储了 AssetBundle 中所有资源的名称、类型、路径、大小、依赖关系等信息。在运行时,通过调用 AssetBundle.LoadAsset 或者 AssetBundle.LoadAllAssets 等方法,可以加载 AssetBundle 中的资源,根据元数据文件中的信息将资源加载到内存中,然后在游戏中使用。
  • Unity AssetBundle 打包时可以设置 AssetBundle 的名称和版本号,这样可以在运行时根据名称和版本号加载 AssetBundle。此外,AssetBundle 也可以设置依赖关系,一个 AssetBundle 中的资源可以依赖于其他的 AssetBundle。当加载一个 AssetBundle 时,如果它依赖于其他的 AssetBundle,Unity 会自动递归加载所有依赖的 AssetBundle。
  • 使用方法:
  • 创建 AssetBundle。在发布游戏之前将游戏中需要加载的资源放入安装包内或发布到指定服务器上
  • 加载 AssetBundle。在游戏运行时,使用 AssetBundle.LoadAsset 或者 AssetBundle.LoadAllAssets 等方法加载 AssetBundle 中的资源。加载 AssetBundle 时需要指定 AssetBundle 的名称和版本号,如果有依赖关系,需要先加载依赖的 AssetBundle。需要严格维护AB包的完整性和保证依赖有序
  • 卸载 AssetBundle。在使用完 AssetBundle 中的资源后,应该及时卸载 AssetBundle。卸载 AssetBundle 只会释放 AssetBundle 对象本身占用的内存,不会释放资源所占用的内存。当不再需要 AssetBundle 中的资源时,可以通过 AssetBundle.Unload 方法卸载 AssetBundle。
  • 更新 AssetBundle。在游戏运行时,如果需要更新 AssetBundle 中的资源,可以使用 UnityWebRequest 下载最新的 AssetBundle 文件,然后加载并替换原来的 AssetBundle。
5. MeshRender中Material和SharedMaterial的区别?


  • Material是Mesh Renderer组件的实例材质,它是该组件所使用的材质的一个副本。这意味着,如果您更改一个对象的Material属性,它将只会影响该对象的渲染,而不会影响其他对象的渲染。
  • SharedMaterial是Mesh Renderer组件的共享材质,它是该组件所使用的材质的原型。这意味着,如果您更改一个对象的SharedMaterial属性,它将会影响所有使用该共享材质的对象的渲染。这使得SharedMaterial特别适用于需要在多个对象之间共享材质的情况,因为它可以减少内存使用量和减少重复材质的数量。
  • 总之,在大多数情况下,我们应该使用SharedMaterial来减少内存使用和提高性能。只有在需要单独更改某个对象的材质时,才应该使用Material属性。
  • 此外,SharedMaterial允许多个对象共享一个材质。这意味着在渲染时可以将它们一起批处理,从而减少Draw Call的数量,提高渲染性能。而如果使用Material,每个对象都有一个单独的材质实例,需要单独绘制,这会增加Draw Call的数量,影响性能。
6. Unity中Mask组件和RectMask2D组件原理上有什么区别?


  • 当渲染Mask组件时,Unity会使用Stencil Buffer来记录该组件的可见区域。然后,当渲染其他UI元素时,Unity会测试Stencil Buffer,并仅渲染在该区域内的像素,从而实现UI遮罩的效果。
  • 子物体组件调用方法设置裁剪区域(SetClipRect)传递给Shader,片元着色器中判断像素是否在矩形区域内并进行剔除
7. 如何解决unity中子弹打到物体的碰撞检测不到的问题?


  • 当子弹在高速运动时,可能会出现子弹打到物体,但是Unity的物理引擎没有检测到碰撞的情况。这是因为物理引擎检测碰撞的方式是基于离散时间步进的,而当子弹速度过快时,可能会出现跨越物体的情况,导致碰撞检测失败。 为了解决这个问题,可以采用以下几种方法:
  • 提高物理引擎的时间步进频率:通过增加Fixed Timestep的值,可以提高物理引擎的时间步进频率,从而提高碰撞检测的准确性。但是过高的频率可能会影响性能。
  • 增加物理引擎的迭代次数:通过增加物理引擎的迭代次数,可以提高碰撞检测的准确性。可以在Project Settings -> Physics中调整迭代次数。
  • 使用射线预测:可以使用Unity的射线检测功能,通过在子弹的运动方向上发射一条射线,检测是否与物体发生碰撞。如果检测到碰撞,可以通过碰撞点的位置和法线信息计算出子弹的反射方向,并将其应用于子弹的运动。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-20 11:29 , Processed in 0.124153 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表