Unity面试知识点整理(持续更新中)

文章目录

🧡 Unity知识面试篇

基础流程

1.3d内容生产和编辑流程

3D内容生产和编辑流程通常包括一系列复杂的步骤,从最初的概念设计到最终的渲染和输出。以下是3D内容生产和编辑的一般流程:

  1. 概念设计

    • 确定3D内容的基本构思,包括角色、环境、对象等的视觉风格和功能需求。
  2. 创建3D模型

    • 使用3D建模软件(如Blender、Maya、3ds Max)创建基础的几何形状和详细模型。
  3. 拓扑优化

    • 优化3D模型的拓扑结构,确保模型在保持细节的同时具有高效的多边形分布。
  4. UV展开

    • 将3D模型的表面展开成2D平面,为纹理贴图做准备。
  5. 纹理贴图

    • 创建和应用纹理贴图,包括漫反射贴图、法线贴图、高光贴图等,以增加模型的真实感。
  6. 材质和着色

    • 设计材质和着色器,定义物体表面的视觉特性,如颜色、光泽、透明度等。
  7. 骨骼绑定和蒙皮

    • 对于角色或可动物体,创建骨骼系统并绑定到模型上,以便进行动画制作。
  8. 动画制作

    • 使用关键帧动画或运动捕捉技术制作角色或物体的动作和表情。
  9. 环境布局

    • 在3D场景中布置环境元素,如建筑物、自然景观、道具等。
  10. 光照和阴影

    • 设置场景的光照效果,包括光源类型、强度、颜色和阴影。
  11. 摄像机设置

    • 确定摄像机的位置和视角,设置镜头参数如焦距、景深等。
  12. 渲染设置

    • 配置渲染参数,包括分辨率、抗锯齿、采样率等,以获得高质量的图像输出。
  13. 模拟和特效

    • 添加物理模拟(如流体、布料、粒子效果)和特效(如光晕、烟雾)。
  14. 后期处理

    • 使用后期处理技术,如颜色校正、滤镜效果、合成等,增强视觉效果。
  15. 性能优化

    • 优化3D场景和动画的性能,确保在目标平台上的流畅运行。
  16. 最终渲染

    • 进行最终渲染,输出高分辨率的图像或动画序列。
  17. 视频编辑和输出

    • 如果是动画或视频项目,进行视频编辑和后期剪辑,然后输出最终视频文件。
  18. 反馈和迭代

    • 根据反馈进行必要的调整和优化,迭代改进3D内容。
  19. 发布和分发

    • 将完成的3D内容发布到相应的平台或媒体,进行市场推广和分发。
2. Unity工作流程
  • 项目设置:创建新的Unity项目,设置项目的基本参数,如质量设置和物理引擎。
  • 资产导入:将3D模型、纹理、音频文件等资源导入Unity。
  • 场景构建:在Unity编辑器中布局场景,包括地形、建筑物、道具等。
  • 游戏对象创建:创建游戏对象(GameObject),并附加组件如Collider、Rigidbody等。
  • 脚本编写:使用C#或其他支持的语言编写脚本,实现游戏逻辑。
  • 动画制作:使用Unity动画系统创建角色和物体的动画。
  • UI设计:设计和实现用户界面,包括菜单、HUD、控制面板等。
  • 测试:在编辑器中进行游戏测试,使用Unity的测试工具进行自动化测试。
  • 性能优化:使用Profiler工具分析和优化游戏性能。
  • 构建和发布:配置构建设置,将游戏构建为可执行文件,并发布到目标平台。
3.unity生命周期

Unity中的生命周期指的是游戏对象(GameObject)和组件从创建到销毁所经历的一系列系统调用过程。理解Unity的生命周期对于管理游戏状态、执行初始化和清理操作非常重要。以下是Unity中的主要生命周期阶段:

  1. Awake

    • 在对象首次成为激活状态时调用,用于初始化。在任何Start方法之前调用,且只会调用一次。
  2. OnEnable

    • 当对象被激活时调用,可以被调用多次,例如当对象从非激活变为激活状态时。
  3. Start

    • 在脚本第一次加载到游戏对象上时调用,通常用于初始化操作,如设置变量和启动Coroutine。
  4. Update

    • 每帧调用一次,主要用于处理游戏逻辑、玩家输入和时间相关的更新。
  5. FixedUpdate

    • 在物理计算之前每固定时间间隔调用一次,主要用于物理相关的更新。
  6. LateUpdate

    • 在Update之后调用,用于执行应该在所有Update方法之后发生的操作。
  7. OnLevelLoad

    • 当加载新场景时调用,可以用于设置场景特定的状态。
  8. OnDisable

    • 当对象变为非激活状态时调用,可以用于保存状态或执行清理操作。
  9. ** OnDestroy**:

    • 当对象被销毁时调用,用于执行必要的清理工作,如取消Coroutine、移除事件监听等。
  10. OnDrawGizmos / OnDrawGizmosSelected

    • 用于在场景视图和游戏视图中绘制辅助的Gizmos,帮助开发者可视化组件的位置和方向。
  11. OnGUI

    • 虽然在较新的Unity版本中已不推荐使用,但在过去用于在Unity编辑器中绘制自定义的图形用户界面。
  12. OnApplicationPause

    • 当应用程序暂停时调用,例如移动设备被切换到后台。
  13. OnApplicationQuit

    • 当应用程序退出时调用,用于执行最后的清理工作。
  14. OnCollisionEnter / OnCollisionStay / OnCollisionExit

    • 分别在发生碰撞、持续碰撞和碰撞结束时调用。
  15. OnTriggerEnter / OnTriggerStay / OnTriggerExit

    • 分别在触发器开始、持续和结束时调用。

物理系统

1.CharacterController 与 Rigidbody 的区别
  • Rigidbody 提供完全基于物理的模拟,受重力、碰撞力和摩擦力等因素的影响,适用于真实的物理交互。
  • CharacterController 是一个简化的物理组件,允许开发者绕过复杂的物理计算来控制角色移动和跳跃,不完全受物理规则限制,适合快速开发和简单角色控制。
2.射线检测碰撞物的原理
  • 射线检测(Raycasting)是从一点出发沿特定方向发射一条虚拟的线,这条线在遇到其他物体时会停止。射线检测常用于检测视野、触发事件或检测障碍物。
3.链条关节 (Hinge Joint) 的概念和用途
  • Hinge Joint 是一种物理关节,模拟两个物体通过铰链连接的情况,允许在一个平面内旋转,常用于门、车轮等场景。
4.物体发生碰撞的必要条件
  • 两个物体都必须具有 Collider 组件,至少一个物体需要附加 Rigidbody 刚体组件以参与物理计算。
5.碰撞过程的不同阶段及其对应的函数
  • OnCollisionEnter:当碰撞开始时调用。
  • OnCollisionStay:当物体持续碰撞时每帧调用。
  • OnCollisionExit:当碰撞结束时调用。
6.Unity3D 中碰撞器和触发器的区别
  • 触发器(Trigger)是碰撞器(Collider)的一个特殊类型,用于检测物体是否穿过了特定的区域,不产生物理碰撞效果,而是通过 OnTriggerEnterOnTriggerStayOnTriggerExit 函数来处理事件。如果既要检测到物体的接触又不想让碰撞检测影 响物体移动或要检测一个物件是否经过空间中的 某个区域这时就可以用到触发器
7.射线 Raycast 原理
  • Raycast 是从发射点沿特定方向发射一条射线,射线遇到物体时返回碰撞信息,用于检测物体间是否直线可到达。
8.Unity3D 物理引擎中施加力的方式
  • 施加力的方式包括:
    • rigidbody.AddForce:在物体上施加一个力。
    • rigidbody.AddForceAtPosition:在物体的特定位置施加一个力,可以产生扭矩。
    • 都在 rigidbody系列函数中。
9.高速物体与大物体碰撞可能出现的问题及解决方法
  • 高速物体可能穿透大物体,即发生“穿透”现象,这通常是由于物理计算的精度问题或时间步长设置不当。
  • 解决方法包括优化碰撞体的形状和大小,调整物理引擎的时间步长,或使用连续碰撞检测(CCD)。
10.物理更新适用的系统函数 FixedUpdate
  • FixedUpdate 是 Unity 用于物理更新的函数,它以固定的时间间隔调用,与渲染帧率无关,适合进行物理计算和刚体的更新。
  • FixedUpdate比较适用于物理引擎的计算,因为是跟每帧渲染有关。 Update就比较适合做控制。
11. Unity中构建复杂场景的经验
  • 场景布局:设计场景的布局,确保逻辑和视觉的连贯性。
  • 导航网格:使用NavMesh系统创建导航网格,让AI能够导航。
  • 场景管理:使用场景管理技术,如场景的动态加载和卸载。

UI & 2D 部分

1.UGUI 合批问题
  • UGUI 合批指的是 Unity 将具有相同材质和纹理的 UI 元素在渲染时合并为一个单一的绘制调用,以提高渲染效率。问题通常与使用不同的材质或纹理有关,例如字体纹理与 UI 元素的纹理不同导致的无法合批。
2.Image 与 RawImage 的区别
  • Image 是用于显示 Sprite 的 UI 组件,支持裁剪、旋转和填充等操作,但性能上可能略低于 RawImage。
  • RawImage 是显示普通纹理的 UI 组件,不支持 Sprite 特有的操作,但渲染性能较好,适用于显示静态图像。
  • Image只能使用Sprite属性的图片,但是RawImage什么样的都可以使用
  • Image适合放一些有操作的图片,裁剪平铺旋转什么的,针对Image Type属性
  • RawImage就放单独展示的图片就可以,性能会比Image好很多
3.实现 2D 游戏的不同方式
  • 使用 UGUI 系统,通过正交摄像机和 Canvas 来创建 2D 界面和游戏元素。
  • 将摄像机设置为正交投影,忽略 Z 轴,模拟 2D 空间。
  • 使用 Unity 的 2D 模式,该模式下场景视图和层级视图将优化为 2D 操作。
  • 利用 2D Toolkit 插件,提供高效的 2D 精灵和文本系统。
4.TextureType 选项为 Texture 和 Sprite 的区别
  • Texture 用于普通的纹理贴图,可以用于模型的表面材质。
  • Sprite 用于 UI 精灵,允许 Unity 进行合批操作,提高 UI 渲染性能。
5.保持 UI 在不同分辨率下一致性的方法
  • 布局元素的位置,即屏幕分辨率变化的情况下,布局元素的位置可能固定不动,导致布局元素可能超出边界;
  • 布局元素的尺寸,即在屏幕分辨率变化的情况下,布局元素的大小尺寸可能会固定不变,导致布局元素之间出现重叠等功能。
  • 为了解决这两个问题,在Unity UGUI体系中有两个组件可以来解决问题,分别是布局元素的Rect Transform和Canvas的Canvas Scaler组件。
  • 使用 Canvas Scaler 组件,特别是其 UI Scale Mode 设置为 “Scale With Screen Size” 模式,根据屏幕分辨率动态缩放 UI 元素。
6.画布的三种模式和缩放模式
  • Screen Space - Overlay 屏幕空间-覆盖模式:与摄像机无关,UI 元素始终在 3D 元素前面。

  • Screen Space - Camera 屏幕空间-摄像机模式:需要指定摄像机,UI 元素在摄像机的投射范围内。

  • World Space 世界空间模式:UI 元素作为世界空间中的物体,可以自由移动和旋转。

  • UI Scale Mode

    • Constant Pixel Size:保持 UI 元素的像素尺寸不变。
    • Scale With Screen Size:根据屏幕尺寸缩放 UI 元素。
    • Constant Physical Size:保持 UI 元素的物理尺寸不变。
7.Text 与 TMPText 的区别及优缺点
  • Text 是旧的 UI 文本组件,使用像素渲染,可能在放大时出现模糊,适合经常变动的文本。

  • TMPText 是 TextMeshPro 包中的新文本组件,使用网格渲染,提供更好的可读性和样式选项,适合大量静态文本,但可能在运行时性能上有所消耗。

  • Text 优点:简单易用,适合动态文本。

  • Text 缺点:可能在高分辨率下模糊,样式选项有限。

  • TMPText 优点:清晰度高,样式丰富,适合大量文本。

  • TMPText 缺点:性能消耗较大,文本数据量大时可能影响性能。

动画系统

1.游戏动画的种类及其原理
  • 关节动画:将角色分割成多个独立部分,每部分对应一个网格模型,通过连接各部分的动画来构成整体动画,提供灵活性。
  • 骨骼动画:结合关节动画的优点,使用骨骼层次结构和关节连接,皮肤蒙在骨骼上,允许相对运动,适用于复杂和逼真的角色动画。
  • 单一网格模型动画(关键帧动画):通过在关键帧记录顶点位置变化,并通过插值计算实现动画效果。
2.Avatar 的作用
  • Avatar 是 Unity 中用于将自定义模型的骨骼结构与 Unity 的动画系统相匹配的组件,支持动画重定向,允许动画在不同的模型上重用。
3.反向旋转动画的方法
  • 将动画的播放速度设置为负值,例如通过代码 animation.speed = -1 实现反向播放。
4.Animation.CrossFade 的用途
  • Animation.CrossFade 用于在一个动画状态淡入时,使另一个动画状态淡出,实现平滑的动画过渡效果。
5.Animation 的五个方法
  1. AddClip:将剪辑添加到动画播放列表。
  2. Blend:在指定时间内将一个动画混合到另一个动画。
  3. CrossFade:实现一个动画向另一个动画的交叉淡入淡出。
  4. IsPlaying:检查指定名称的动画是否正在播放。
  5. Stop:停止所有正在播放的动画。
6.SkinnedMesh 实现原理
  • SkinnedMesh 通过骨骼(Bone)和蒙皮(Skin)实现动画。骨骼构成层次结构,存储变换数据;蒙皮是网格顶点附着在骨骼上,根据骨骼的运动进行变形。
7.动画层 (Animation Layers) 的作用
  • 动画层允许开发者在不同的层上控制角色的不同部分的动画,实现复杂动画的叠加和混合,如上半身和下半身的独立动画。
8.Animation 与 Animator 的区别
  • Animation:是较旧的动画系统,用于控制单个动画剪辑的播放,不涉及复杂的动画状态机。
  • Animator:是较新的动画系统,使用动画控制器(Animator Controller)来管理复杂的动画状态机和动画层,适合实现复杂的动画逻辑和过渡。
4. 导入和操作3D模型以及使用Unity动画系统
  • 模型导入:将3D模型从软件如Maya、Blender导入Unity。
  • 模型操作:在Unity中调整模型的位置、旋转和缩放。
  • 动画制作:使用Animation窗口创建关键帧动画,或导入动画数据。
  • 动画控制器:使用Animator Controller来管理动画状态机和动画层。

协程

1.进程、线程、协程的概念
  • 进程:是运行中的程序实例,具有独立的内存空间,是资源分配的基本单位。
  • 线程:线程从属于进程,是进程中的一个执行流,负责执行程序的指令,是程序执行的最小单元,共享进程的内存空间。
  • 协程:是一种程序组件,允许挂起和恢复执行,用于实现异步操作,不涉及多任务操作系统的调度。
2.协程的作用和底层原理
  • 作用:协程用于执行需要等待的操作(如IO、网络请求等),而不会阻塞主线程,从而提高程序的响应性和效率。
  • 底层原理:协程通过 IEnumerator 接口和 yield 关键字实现。StartCoroutine 启动协程,协程中的 yield 语句用于控制执行流程和挂起点。协程在 Unity 中以帧为单位执行,通过 MoveNext 方法控制流程。
3.线程与协程的区别
  • 线程:由操作系统管理,支持真正的并行执行,适合计算密集型任务,但创建和上下文切换开销较大。
  • 协程:由程序控制,在同一线程内通过协作交替执行,适合 IO 密集型或需要异步操作的场景,开销较小。
4.协同程序的执行代码、用处和缺点
  • 执行代码
    IEnumerator MyCoroutine()
    {
        // 执行一些操作
        yield return new WaitForSeconds(2); // 等待2秒
        // 继续执行后续操作
    }
    
  • 用处
    • 实现异步操作,避免阻塞主线程。
    • 简化编写需要等待的操作的代码逻辑。
    • 提供更细粒度的控制,如加载资源、等待用户输入等。
  • 缺点
    • 可能不适合计算密集型任务,因为协程仍然在单一线程内执行。
    • 错误处理相对复杂,需要考虑协程的挂起和恢复状态。
    • 过多的协程可能导致代码难以管理和跟踪。

数据持久化 & 资源管理&性能优化

1.Unity 常用资源路径
  • Application.dataPath: 返回包含"Assets"目录的文件夹的完整路径。
  • Application.streamingAssetsPath: 指向"StreamingAssets"文件夹的路径,这个文件夹用于存放需要从应用内部访问的资源。
  • Application.persistentDataPath: 返回可用于存储持久数据的路径,如保存游戏进度。
2.安全地在不同工程间迁移 asset 数据的方法
  • 迁移 Assets 和 Library 文件夹:将整个 “Assets” 文件夹和 “Library” 文件夹复制到新工程。
  • 使用 Unity 包:将资源打包成 .unitypackage 文件,然后在新工程中导入。
  • 使用 Unity Asset Server:利用 Unity 的资产管理系统进行资源的版本控制和迁移。
3.PlayerPrefs 类保存和读取整形数据的函数
  • PlayerPrefs.SetInt(string key, int value): 保存整型数据。
  • PlayerPrefs.GetInt(string key, int defaultValue): 根据提供的 key 读取整型数据,如果 key 不存在则返回默认值。
4.动态加载资源的方式
  • Instantiate: 实例化场景中的 prefab 或者通过 Resources.Load 加载的资源。
  • AssetBundle: 将资源打包成 .assetbundle 文件,然后在需要时动态加载。
  • Resources.Load: 加载位于 “Resources” 文件夹下的资源。
  • AssetDatabase.LoadAssetAtPath: 在编辑器模式下加载资源,不推荐在运行时使用。
5.AssetsBundle 打包和加载方法
  • 打包:使用 BuildPipeline.BuildAssetBundles 方法将资源打包成 AssetBundle 文件。
  • 加载
    • AssetBundle.LoadFromFileAsync: 从文件系统异步加载 AssetBundle。
    • AssetBundle.LoadFromMemoryAsync: 从内存中加载 AssetBundle。
    • UnityWebRequest: 通过网络下载 AssetBundle。
6.AssetBundle 卸载流程
  • AssetBundle.Unload(bool unloadAllLoadedObjects): 卸载 AssetBundle。如果参数为 true,则卸载所有加载的对象;如果为 false,则只卸载未使用的对象。
7.ScriptableObject 的用途和优势
  • 用途:ScriptableObject 用作数据容器,可以存储各种类型的数据,常用于配置数据或游戏状态。
  • 优势
    • 避免值拷贝:与 MonoBehaviour 不同,ScriptableObject 不会自动复制实例数据,从而减少内存占用。
    • 复用性:可以在多个地方引用同一个 ScriptableObject 实例,提高数据复用性。
    • 灵活性:可以在编辑器中创建和管理 ScriptableObject 资源,提供更多的灵活性和便利性。

ScriptableObject 是 Unity 中处理数据和配置的一种高效方式,特别是在需要存储大量数据或跨多个场景和对象共享数据时。

8.热更新

Unity的热更新,通常指的是在不重新构建和部署整个应用程序的情况下,能够更新应用程序的部分内容或功能。这在游戏开发中尤其重要,因为它允许开发者修复bug、添加新内容或进行平衡调整,而无需玩家下载全新的游戏版本。以下是实现Unity热更新的一些常见方法:

  1. Asset Bundles

    • 使用Asset Bundles来管理和更新游戏的资源。通过动态加载和卸载Asset Bundles,可以在运行时更新游戏的资源和数据。
  2. Addressable Assets System

    • Unity的Addressable系统提供了一种更高级的资源管理方式,支持按需加载和更新资源,非常适合热更新。
  3. Lua Scripting

    • 使用Lua作为脚本语言,通过XLua或UniLua等绑定库,可以实现逻辑代码的热更新,因为Lua脚本可以在运行时重新加载。
  4. C# Scripting with Reflection

    • 利用C#的反射功能,可以在运行时加载和替换C#脚本,实现逻辑的热更新。
  5. Il2cpp Binary

    • 使用Il2cpp将C#代码编译成二进制文件,然后通过特定的热更新框架或自定义的解决方案来更新这些二进制文件。
  6. Custom Patching System

    • 开发自定义的补丁系统,通过下载差分更新包来更新游戏内容,而不是整个游戏。
  7. Network Streaming

    • 通过网络流式传输技术,将更新内容实时推送给客户端。
  8. Plugins and Extensions

    • 使用第三方插件和扩展,如UTiny or Hotfix,这些工具提供了热更新的支持。
  9. Version Control

    • 通过版本控制系统管理更新,确保热更新内容的版本一致性和可追溯性。
  10. Fallback Mechanisms

    • 设计失败回退机制,如果热更新失败,能够确保玩家能够回退到稳定版本。

C#

1.什么是反射以及反射的原理

反射(Reflection)是一种程序功能,它允许程序在运行时查询和修改自身的结构和行为。在.NET框架和C#语言中,反射提供了一种机制,通过这种机制可以在运行时访问和操作类型信息、创建类型的实例、调用方法、访问字段和属性等。

反射的原理:

  1. 元数据

    • .NET程序集(Assembly)包含元数据,这些数据描述了程序集中定义的类型、方法、属性等。反射利用这些元数据来获取类型信息。
  2. Type类

    • System.Type类是所有类型信息的基类。通过Type对象,可以访问类的名称、属性、方法、字段等信息。
  3. 程序集加载

    • 程序集(Assembly)是编译后的代码和资源的容器。使用反射时,首先需要加载程序集。
  4. 类型获取

    • 通过程序集可以获取类型定义,然后创建Type对象的实例。
  5. 类型信息查询

    • 使用Type对象的方法和属性,可以查询类型的详细信息,例如类的基类、接口、构造函数、方法、属性和字段。
  6. 动态创建实例

    • 通过Activator类或Type对象的GetConstructorInvoke方法,可以在运行时创建类型的实例。
  7. 成员访问

    • 通过反射可以访问类型的私有和公共成员,包括字段、属性和方法。
  8. 调用成员

    • 使用MethodInfoFieldInfoPropertyInfo等反射对象,可以在运行时调用方法、访问字段和属性值。
  9. 泛型和属性

    • 反射支持泛型类型和方法的操作,以及读取和应用自定义属性(Attributes)。
  10. 性能考虑

    • 反射通常比直接代码调用要慢,因为它涉及额外的解析和运行时查找。
  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值