36.Unity入门基础知识总结

  1. 36.总结
    1. 36.1 知识点
      1. 学习的主要内容
      2. 总结讲什么
      3. 学习Unity是学习什么
      4. 如何学好Unity
      5. 强调
    2. 36.2 核心要点速览
      1. 生命周期函数和打印信息
        1. 生命周期函数详解
        2. 在 Unity 中打印信息
      2. Unity 特性
        1. 变量可见性控制
        2. 自定义类型序列化
        3. 辅助特性(提升可读性)
        4. 交互增强特性
      3. 基础属性和组件的获取
        1. 重要成员
        2. 重要方法
      4. GameObject 游戏对象
        1. GameObject 成员变量
        2. GameObject 静态方法
        3. GameObject 成员方法
        4. 次要成员方法(不建议使用,效率低)
      5. Time 时间
      6. Transform
        1. Transform 概述
        2. Vector3 三维向量
        3. 位置
        4. 朝向
        5. 位移
        6. 角度和旋转
        7. 缩放
        8. 看向
        9. 父子关系
        10. 坐标转换
      7. Input 组件
        1. 鼠标输入(Update 中使用)
        2. 键盘输入(Update 中使用)
        3. 虚拟轴输入(控制移动/旋转)
        4. 触摸输入(移动设备)
        5. 手柄/虚拟按钮
        6. 重力感应(陀螺仪)
      8. Screen 屏幕
      9. Camera 摄像机
        1. Camera 组件参数
        2. Camera 参数和方法
          1. 获取摄像机相关
          2. 渲染相关委托
          3. 重要成员
      10. Light 光面板
        1. 光源组件
        2. 光面板(照明设置)
      11. 物理系统 - 刚体
        1. 刚体组件参数
        2. 刚体参数和方法
      12. 物理系统 - 碰撞体
        1. 3D 碰撞器种类
        2. 3D 碰撞器共同参数
        3. 常用碰撞器
        4. 不常用碰撞器
      13. 物理系统 - 物理材质
      14. 碰撞检测函数
        1. 碰撞器与触发器的核心条件对比
          1. 碰撞发生的必要条件
          2. 触发器触发的必要条件
        2. 物理碰撞检测响应函数
        3. 触发器检测响应函数
      15. Unity 音效系统
        1. 音频文件导入
        2. 音频源(AudioSource)
          1. 音频源组件参数
          2. 音频源参数和方法
        3. 麦克风录制
    3. 36.3 面试题精选
      1. 基础题
        1. 1. Unity 工程中 Assets 与 ProjectSettings 各自存什么?删错会怎样?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. 为什么 Inspector 能显示脚本字段?SerializeField 和 public 各解决什么问题?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. 预设体实例上的 Overrides、Apply、Unpack 分别是什么操作?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        4. 4. GameObject.Find 类 API 的共性限制与性能风险?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        5. 5. Time.deltaTime 与 Time.unscaledDeltaTime 何时选用?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        6. 6. Screen.currentResolution 与 Screen.width / Screen.height 有何区别?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        7. 7. 使用 Camera.main 的前提与常见坑?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
      2. 进阶题
        1. 1. 场景文件 .unity 本质上是什么?把别的场景拖进当前场景一般做什么?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. Awake、OnEnable、Start 的调用时机与大致顺序?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. GetComponentInChildren 的 includeInactive 何时要设为 true?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        4. 4. Destroy 与 DestroyImmediate 有何区别?为何优先 Destroy?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        5. 5. position 与 localPosition 何时与 Inspector 上看到的「一致」?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        6. 6. Transform.Find 与 GameObject.Find 在范围与失活对象上的差异?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        7. 7. 多摄像机叠加时,Depth 与 Clear Flags(如 Depth only)如何配合?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        8. 8. 物理「碰撞回调」与「触发器回调」分别在什么条件下触发?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        9. 9. Rigidbody.isKinematic 开启后行为如何?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
      3. 深度题
        1. 1. 脚本执行顺序(Script Execution Order)解决什么问题?滥用会怎样?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. FixedUpdate 与 Update、物理帧之间是什么关系?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. SetParent 的 worldPositionStays 为 true 或 false 时分别发生什么?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        4. 4. TransformPoint 与 TransformDirection、TransformVector 在「是否受缩放影响」上如何区分?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        5. 5. Input.GetAxis 与 Input.GetAxisRaw 的区别与典型用法?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        6. 6. ScreenToWorldPoint 里为什么要改 z?和 Physics.Raycast 选点的思路差异?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        7. 7. ForceMode.Acceleration、Force、Impulse、VelocityChange 如何选用?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        8. 8. 场景中 AudioListener 与 Spatial Blend 分别要解决什么问题?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章

36.总结


36.1 知识点

学习的主要内容

总结讲什么

学习Unity是学习什么

如何学好Unity

强调


36.2 核心要点速览

生命周期函数和打印信息

生命周期函数详解

函数名 调用时机 用途
Awake 对象(脚本类对象)被创建时调用 类似构造函数,可进行对象创建时的初始化操作
OnEnable 对象被激活时调用 可在此处编写对象激活时的逻辑处理代码,运行游戏时自动调用一次
Start 对象第一次帧更新前执行 用于编写初始化逻辑,执行时间比 Awake 晚
FixedUpdate 每一物理帧执行 主要用于物理更新,物理帧与游戏帧不同
Update 每一游戏帧执行 用于处理游戏核心逻辑更新
LateUpdate 比 Update 晚执行 一般用于处理摄像机位置更新相关内容
OnDisable 对象失活时调用 可在此处编写对象失活时的处理逻辑
OnDestroy 对象被销毁时调用 销毁前对象失活,会先调用 OnDisable

在 Unity 中打印信息

方法 用途
Debug 类 Log 方法 打印普通信息,如 Debug.Log("Awake Debug.Log");
Debug 类 LogWarning 方法 打印警告信息,如 Debug.LogWarning("警告");
Debug 类 LogError 方法 打印报错信息,如 Debug.LogError("错误");
MonoBehaviour 类 print 方法 继承时可使用,如 print("Awake print");

Unity 特性

变量可见性控制

特性 作用 适用变量 语法 关键说明
[SerializeField] 强制私有/保护变量显示 private/protected [SerializeField] private int value; 序列化字段,支持基本类型、数组、GameObject 等;运行时修改影响成员变量
[HideInInspector] 隐藏公共变量 public 变量 [HideInInspector] public int value; 代码可访问,但 Inspector 不显示
默认公共变量 直接显示 public 变量 public int value; 简单直接,但暴露所有公共字段

自定义类型序列化

类型 显示条件 示例 关键说明
枚举 直接显示(无需额外特性) public E_TestEnum enumValue; 下拉菜单选择枚举值
结构体 [System.Serializable] 特性 [Serializable] public struct MyStruct{...} 序列化后可展开编辑字段
[System.Serializable] 特性 + 继承 UnityEngine.Object 或标记为 [CreateAssetMenu] [Serializable] public class MyClass{...} 非 MonoBehaviour 需手动序列化;ScriptableObject 需 [CreateAssetMenu]
集合 直接显示(数组、List public int[] array;
public List<int> list;
支持动态添加/删除元素(List 需初始化)

辅助特性(提升可读性)

特性 作用 参数 示例
[Header(“标题”)] 分组标题(字段上方) 字符串(如 “基础属性”) [Header("战斗属性")] public int atk;
[Tooltip(“提示”)] 悬停提示 字符串 [Tooltip("闪避率")] public float miss;
[Space(像素)] 字段间隔 可选像素值 [Space(20)] public int crit;
[Range(Min, Max)] 数值滑条 最小值,最大值 [Range(0, 10)] public float luck;
[Multiline(行数)] 多行文本框 可选行数 [Multiline(5)] public string tips;
[TextArea(Min, Max)] 滚动文本框 最小行数,最大行数 [TextArea(3, 4)] public string desc;

交互增强特性

特性 作用 参数 示例
[ContextMenuItem(“按钮名”, “方法”)] 为变量添加右键快捷方法 按钮文本,方法名 [ContextMenuItem("重置", "ResetMoney")] public int money;
[ContextMenu(“按钮名”)] 为方法添加 Inspector 执行按钮 按钮文本 [ContextMenu("测试逻辑")] private void Test();

基础属性和组件的获取

重要成员

成员 说明 示例
gameObject 获取脚本依附的 GameObject print(gameObject.name);
transform 获取位置信息 print(transform.position);
enabled 获取或设置脚本激活状态 this.enabled = false;

重要方法

方法 作用 参数 示例
GetComponent 获取单个挂载脚本 可按脚本名、Type、泛型获取 var script = GetComponent<MyScript>();
GetComponents 获取多个挂载脚本 泛型 var scripts = GetComponents<MyScript>();
GetComponentInChildren 获取子对象挂载的单个脚本 bool:是否查找失活子对象,默认 false var childScript = GetComponentInChildren<MyScript>(true);
GetComponentsInChildren 获取子对象挂载的多个脚本 bool:是否查找失活子对象,默认 false;可传入 List 接收结果 GetComponentsInChildren<MyScript>(true, list);
GetComponentInParent 获取父对象挂载的单个脚本 var parentScript = GetComponentInParent<MyScript>();
GetComponentsInParent 获取父对象挂载的多个脚本 var parentScripts = GetComponentsInParent<MyScript>();
TryGetComponent 安全获取单个脚本 泛型,使用 out 输出结果 if (TryGetComponent<MyScript>(out var script)) { ... }

GameObject 游戏对象

GameObject 成员变量

变量 说明 示例
name 对象名称 print(gameObject.name);
gameObject.name = "新名称";
activeSelf 对象是否激活 print(gameObject.activeSelf);
isStatic 对象是否为静态对象 print(gameObject.isStatic);
layer 对象的层级 print(gameObject.layer);
tag 对象的标签 print(gameObject.tag);
transform 位置、旋转和缩放信息 print(gameObject.transform.position);

GameObject 静态方法

方法 作用 注意事项 示例
CreatePrimitive 创建带原始网格和碰撞体的对象 GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
Find 通过对象名查找激活对象 效率低,找不到返回 null,无法找失活对象 GameObject obj = GameObject.Find("对象名");
FindWithTag 通过标签查找单个激活对象 同上 GameObject obj = GameObject.FindWithTag("标签名");
FindGameObjectsWithTag 通过标签查找多个激活对象 返回空数组 GameObject[] objs = GameObject.FindGameObjectsWithTag("标签名");
FindObjectOfType 找到场景中挂载某脚本的对象 效率低,遍历对象和脚本 var scriptObj = GameObject.FindObjectOfType<MyScript>();
Instantiate 实例化(克隆)对象 GameObject clone = GameObject.Instantiate(original);
Destroy 删除对象 异步,下一帧移除,建议优先使用 GameObject.Destroy(obj, 5); // 5 秒后删除
DestroyImmediate 立即删除对象 可能造成卡顿 GameObject.DestroyImmediate(obj);
DontDestroyOnLoad 过场景不移除对象 GameObject.DontDestroyOnLoad(obj);

GameObject 成员方法

方法 作用 示例
构造函数 创建空物体 GameObject obj = new GameObject("物体名", typeof(脚本1), typeof(脚本2));
AddComponent 为对象添加脚本 var script = obj.AddComponent<MyScript>();
GetComponent 得到对象的脚本 var script = obj.GetComponent<MyScript>();
CompareTag 标签比较 if (gameObject.CompareTag("标签名")) { ... }
SetActive 设置对象激活/失活 obj.SetActive(false);

次要成员方法(不建议使用,效率低)

方法 作用 示例
SendMessage 广播自己执行方法 gameObject.SendMessage("方法名", 参数);
BroadcastMessage 广播自己和所有子对象执行方法 gameObject.BroadcastMessage("方法名");
SendMessageUpwards 广播自己和所有父对象执行方法 gameObject.SendMessageUpwards("方法名");

Time 时间

分类 变量 说明 受 timeScale 影响 使用场景 示例代码
时间缩放比例 timeScale 控制时间流逝的标度,可用于慢动作、暂停等效果。默认值为 1 - 实现游戏暂停、倍速 Time.timeScale = 0; // 时间停止
Time.timeScale = 2; // 2 倍速
普通帧间隔时间 deltaTime 完成上一帧所用的时间(秒) 游戏暂停时物体停止移动 print("帧间隔时间: " + Time.deltaTime);
transform.Translate(Vector3.forward * speed * Time.deltaTime);
(Update 内) unscaledDeltaTime 独立于 timeScale 的时间间隔(秒) 不受暂停影响的位移计算 print("不受 scale 影响的帧间隔时间: " + Time.unscaledDeltaTime);
transform.Translate(Vector3.forward * speed * Time.unscaledDeltaTime);
游戏开始时间 time 自游戏启动以来受 timeScale 影响的时间(秒) 受时间缩放影响的计时 print("受 scale 影响的游戏时间: " + Time.time);
(计时功能) unscaledTime 独立于 timeScale 的时间(秒) 不受时间缩放影响的计时 print("不受 scale 影响的游戏时间: " + Time.unscaledTime);
物理帧间隔时间 fixedDeltaTime 执行物理更新的时间间隔(秒) 物理模拟计算 print("受 scale 影响的物理帧间隔: " + Time.fixedDeltaTime);
(FixedUpdate 内) fixedUnscaledDeltaTime 独立于 timeScale 的物理帧间隔(秒) 不受时间缩放影响的物理模拟 print("不受 scale 影响的物理帧间隔: " + Time.fixedUnscaledDeltaTime);
帧数 frameCount 从游戏开始到现在运行的总帧数 帧同步、帧率统计 print("总帧数: " + Time.frameCount);

Transform

Transform 概述

Transform 主要用于游戏对象的位移、旋转、缩放、父子关系、坐标转换等操作。

Vector3 三维向量

分类 说明 示例
声明方式 无参构造后赋值;传 xy/z 坐标构造;结构体声明后赋值 Vector3 v1 = new Vector3(10, 10, 10);
Vector3 v2 = new Vector3(10, 10);(z=0)
基本计算 支持 +、 -、 *、 / 运算 Vector3 v1 = new Vector3(1, 1, 1);
Vector3 v2 = new Vector3(2, 2, 2);
print(v1 + v2); // (3.0, 3.0, 3.0)
常用向量 提供如 Vector3.zero、Vector3.right 等 print(Vector3.zero); // (0, 0, 0)
距离计算 Distance 方法返回向量之间的距离 print(Vector3.Distance(v1, v2)); // 1.732051

位置

变量 说明 注意事项 示例
position 相对世界坐标系的坐标 不能单独修改 xyz,只能整体赋值 print(this.transform.position);
this.transform.position = new Vector3(10, 10, 10);
localPosition 相对父对象的坐标 若想以面板坐标为准设置位置,使用此变量 print(this.transform.localPosition);
this.transform.localPosition = Vector3.up * 10;

朝向

可通过 transform.forwardtransform.uptransform.right 得到对象的面朝向、头顶朝向、右手边朝向。

位移

方式 说明 示例
手动计算 路程 = 方向 * 速度 * 时间,放在 Update 里 this.transform.position += this.transform.forward * 1 * Time.deltaTime;
Translate 方法 根据方向和距离移动,可指定相对坐标系 this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.World);

角度和旋转

分类 变量/方法 说明 注意事项 示例
角度 rotation 返回旋转的四元数 - print(this.transform.rotation);
eulerAngles 相对世界坐标角度 不能单独设置 xyz,用 Vector3 赋值 print(this.transform.eulerAngles);
this.transform.eulerAngles = new Vector3(10, 10, 10);
localEulerAngles 相对父对象角度 若想改变面板显示角度,使用此变量 print(this.transform.localEulerAngles);
this.transform.localEulerAngles = new Vector3(10, 10, 10);
旋转 Rotate 方法 自转,有多种重载方式 一般放在 Update 内 this.transform.Rotate(new Vector3(0, 100, 0) * Time.deltaTime);
this.transform.Rotate(Vector3.right, 10 * Time.deltaTime, Space.World);
RotateAround 方法 相对于某一点转 - this.transform.RotateAround(Vector3.zero, Vector3.right, 10 * Time.deltaTime);

缩放

变量 说明 注意事项 示例
lossyScale 相对世界坐标系的缩放大小(只读) 只能获取,不能改变 print(this.transform.lossyScale);
localScale 相对本地坐标系的缩放大小 一般修改此变量,不能只改 xyz print(this.transform.localScale);
this.transform.localScale += Vector3.one * Time.deltaTime;

看向

LookAt 方法可让对象面朝向某一点或对象,一般写在 Update 内持续更新:

  • this.transform.LookAt(Vector3.zero); 看向世界坐标原点
  • this.transform.LookAt(lookAtObj.transform); 看向目标对象

父子关系

操作 变量/方法 说明 示例
获取父对象 parent 变量 获取父对象,返回父对象的 transform print(this.transform.parent);
print(this.transform.parent.name);
设置父对象 parent 变量 断绝父子关系或设置新父对象 this.transform.parent = null;
this.transform.parent = GameObject.Find("Father2").transform;
SetParent 方法 可指定是否保留世界坐标信息 this.transform.SetParent(null);
this.transform.SetParent(fatherTransform, false);(不保留世界坐标)
断绝子对象 DetachChildren 方法 断绝与所有子对象的关系 this.transform.DetachChildren();
获取子对象 Find 方法 按名字查找儿子,能找到失活对象 print(this.transform.Find("Cube (1)").name);
childCount 变量 得到儿子数量,失活儿子也算 print(this.transform.childCount);
GetChild 方法 遍历所有儿子 for (int i = 0; i < this.transform.childCount; i++) { print(this.transform.GetChild(i).name); }
儿子操作 IsChildOf 方法 判断是否为某对象的子项 if (son.IsChildOf(this.transform)) { print("是儿子"); }
GetSiblingIndex 方法 得到自己的编号 print(son.GetSiblingIndex());
SetAsFirstSibling 方法 设置为第一个儿子 son.SetAsFirstSibling();
SetAsLastSibling 方法 设置为最后一个儿子 son.SetAsLastSibling();
SetSiblingIndex 方法 设置为指定编号的儿子 son.SetSiblingIndex(1);

坐标转换

转换类型 方法 说明 示例
世界坐标转本地坐标 InverseTransformPoint 方法 世界坐标系的点转换为本地坐标的点 print("转换后的点 " + this.transform.InverseTransformPoint(Vector3.forward));
InverseTransformDirection 方法 世界坐标系的方向转换为本地方向(不受缩放影响) print("转换后的方向(不受缩放影响)" + this.transform.InverseTransformDirection(Vector3.forward));
InverseTransformVector 方法 世界坐标系的方向转换为本地方向(受缩放影响) print("转换后的方向(受缩放影响)" + this.transform.InverseTransformVector(Vector3.forward));
本地坐标转世界坐标 TransformPoint 方法 本地坐标系的点转换为世界坐标的点(受缩放影响) print("本地 转 世界 点" + this.transform.TransformPoint(Vector3.forward));
TransformDirection 方法 本地坐标系的方向转换为世界方向(不受缩放影响) print("本地 转 世界 方向" + this.transform.TransformDirection(Vector3.forward));
TransformVector 方法 本地坐标系的方向转换为世界方向(受缩放影响) print("本地 转 世界 方向" + this.transform.TransformVector(Vector3.forward));

Input 组件

鼠标输入(Update 中使用)

方法/属性 说明 参数/返回值 示例 注意事项
mousePosition 鼠标屏幕坐标(左下角为原点) Vector3(x,y 像素坐标) print(Input.mousePosition); 屏幕坐标系:x 右,y 上,z=0
GetMouseButtonDown(0/1/2) 鼠标按键按下瞬间(0=左,1=右,2=中) int 键索引,返回 bool if (Input.GetMouseButtonDown(0)) 射击(); 仅按下帧触发一次
GetMouseButtonUp(0/1/2) 鼠标按键抬起瞬间 int 键索引,返回 bool if (Input.GetMouseButtonUp(1)) 取消(); 仅抬起帧触发一次
GetMouseButton(0/1/2) 鼠标按键长按(持续触发) int 键索引,返回 bool if (Input.GetMouseButton(2)) 旋转(); 按住期间每帧触发
mouseScrollDelta 鼠标滚轮滚动量(y 轴为主) Vector2(y=-1 下滚,y=1 上滚) float scroll = Input.mouseScrollDelta.y; 滚轮滚动时触发,非持续

键盘输入(Update 中使用)

方法/属性 说明 参数/返回值 示例 注意事项
GetKeyDown(KeyCode.W) 键盘按下瞬间(枚举或小写字符串) KeyCode 枚举或 “w” 字符串,返回 bool if (Input.GetKeyDown(KeyCode.Space)) 跳跃(); 枚举大写(如 KeyCode.W),字符串小写(如 “w”)
GetKeyUp(KeyCode.W) 键盘抬起瞬间 KeyCode,返回 bool if (Input.GetKeyUp("q")) 换弹(); 仅抬起帧触发一次
GetKey(KeyCode.W) 键盘长按(持续触发) KeyCode,返回 bool if (Input.GetKey(KeyCode.LeftShift)) 加速(); 按住期间每帧触发
inputString 按下的键盘字符(如字母、数字) string(只读) if (Input.anyKeyDown) print(Input.inputString); 仅在 anyKeyDown 帧有效
anyKeyDown 任意键/鼠标按下瞬间 bool(只读) if (Input.anyKeyDown) 开始游戏(); 包括鼠标和键盘

虚拟轴输入(控制移动/旋转)

方法 说明 返回值范围 默认轴 示例 适用场景
GetAxis(“Horizontal”) 平滑轴(渐变值,-1~1) float(如 -0.5, 0.8) Horizontal(A/D 或 左摇杆) transform.Translate(Vector3.right * Input.GetAxis("Horizontal")); 角色移动、镜头旋转
GetAxisRaw(“Vertical”) 离散轴(仅 -1/0/1) float(-1/0/1) Vertical(W/S 或 上摇杆) if (Input.GetAxisRaw("Fire1") > 0) 开火(); 技能触发、跳跃
GetAxis(“Mouse X/Y”) 鼠标移动增量(屏幕像素速度) float(-1~1) Mouse X(鼠标左右) camera.Rotate(0, Input.GetAxis("Mouse X"), 0); 镜头旋转

触摸输入(移动设备)

方法/属性 说明 示例 注意事项
touchCount 当前触摸点数(只读) if (Input.touchCount >= 2) 缩放(); 需开启 Edit > Project Settings > Input Manager > Multi Touch
touches[0].position 第 0 个触摸点屏幕坐标 Vector2 pos = Input.touches[0].position; 触摸点索引从 0 开始
touches[0].deltaPosition 触摸点相对上次位置的偏移量 Vector2 delta = Input.touches[0].deltaPosition; 用于滑动控制(如移动角色)
multiTouchEnabled 是否启用多点触控 Input.multiTouchEnabled = true; 默认为 true,禁用后仅识别第一个触摸点

手柄/虚拟按钮

方法 说明 参数 示例 配置
GetButtonDown(“Jump”) 手柄按钮按下瞬间 string 按钮名(如 “Jump”) if (Input.GetButtonDown("Jump")) 跳跃(); 在 Edit > Project Settings > Input Manager 中配置
GetButton(“Fire”) 手柄按钮长按 string 按钮名 if (Input.GetButton("Fire")) 持续射击(); 支持键盘/手柄映射

重力感应(陀螺仪)

属性 说明 示例 注意事项
gyro.enabled 启用陀螺仪(需先开启) Input.gyro.enabled = true; 移动设备专属,PC 需模拟
gyro.gravity 重力加速度向量(世界坐标系) Vector3 gravity = Input.gyro.gravity; 手机倾斜时返回重力方向(如平放时 (0, -1, 0))
gyro.rotationRate 旋转角速度(弧度/秒) float rotation = Input.gyro.rotationRate.z; 手机旋转时的角速度

Screen 屏幕

分类 变量/方法 说明 示例 注意事项
静态属性(常用) currentResolution 当前屏幕分辨率,返回 Resolution 类对象 Resolution resolution = Screen.currentResolution; 得到的是显示器分辨率,不是 Game 窗口的
width、height Game 窗口当前宽高 print("Game窗口宽: " + Screen.width);
print("Game窗口高: " + Screen.height);
用于代码中用 Game 窗口宽高做计算
sleepTimeout 屏幕休眠模式 Screen.sleepTimeout = SleepTimeout.NeverSleep;
Screen.sleepTimeout = SleepTimeout.SystemSetting;
-
静态属性(不常用) fullScreen 运行时是否全屏模式 Screen.fullScreen = true; -
fullScreenMode 窗口模式(FullScreenMode 枚举) Screen.fullScreenMode = FullScreenMode.Windowed; 可选择独占全屏、全屏窗口等
移动设备旋转屏幕 autorotateToLandscapeLeft 允许自动旋转为左横向 Screen.autorotateToLandscapeLeft = true; -
autorotateToLandscapeRight 允许自动旋转为右横向 Screen.autorotateToLandscapeRight = true; -
autorotateToPortrait 允许自动旋转到纵向 Screen.autorotateToPortrait = true; -
autorotateToPortraitUpsideDown 允许自动旋转到纵向倒置 Screen.autorotateToPortraitUpsideDown = true; -
orientation 指定屏幕显示方向 Screen.orientation = ScreenOrientation.Landscape; -
静态方法 SetResolution 设置分辨率(一般移动设备不使用) Screen.SetResolution(1920, 1080, false); -

Camera 摄像机

Camera 组件参数

分类 参数 说明 用途 示例或注意事项
Clear Flags Skybox(天空盒) 3D游戏适用,渲染天空盒 3D游戏开发 -
(清除标志) Solid Color(纯色) 2D游戏适用,可修改背景颜色 2D游戏开发 在 Background 中选择颜色
Depth only(仅深度) 只画该层,背景透明,用于多摄像机叠加 多摄像机渲染 高深度摄像机常选此模式,配合层级选择
Don’t Clear(不清除) 覆盖渲染,较少使用 特殊渲染需求 -
Background - 没有天空盒时的背景颜色 设置背景颜色 选择合适的背景颜色
Culling Mask - 选择性渲染对象层级 控制渲染对象层级 在检视面板中将层分配到对象
Projection Perspective(透视模式) 3D游戏适用,有近大远小效果 3D游戏开发 FOV Axis 控制视野轴,Field of view 控制视角
(投影) Orthographic(正交模式) 2D游戏适用,无近大远小效果 2D游戏开发 Size 控制视野范围
Clipping Planes - 确定对象渲染的距离区间 控制对象渲染范围 对象渲染异常可能与此参数有关
Viewport Rect - 摄像机视图在屏幕的位置和大小 多摄像机游戏 XY 为起始位置,宽高为比例
Depth - 摄像机渲染顺序,值越大越靠上 控制摄像机渲染顺序 低深度先渲染,高深度后渲染
Rendering path - 定义渲染方法 选择渲染方式 -
Target Texture - 渲染到纹理(如小地图) 制作小地图等 创建 Render Texture 并拖拽到该属性
Occlusion Culling - 启用遮挡剔除,优化渲染性能 优化渲染性能 默认勾选,减少不必要渲染
HDR - 启用高动态范围渲染 提升画面质量 -
MSAA - 启用多重采样抗锯齿 提升画面平滑度 -
Allow Dynamic Resolution - 启用动态分辨率渲染 优化性能 -
Target Display - 定义渲染到的外部设备 多屏幕平台游戏开发 -
Target Eye - VR游戏中选择渲染的眼睛 VR游戏开发 -

Camera 参数和方法

获取摄像机相关
静态成员 说明 示例代码 注意事项
main 获取主摄像机(tag 为 “MainCamera”) print(Camera.main); 场景必须有 tag 为 “MainCamera” 的摄像机,否则报错
allCamerasCount 获取场景中摄像机数量 print(Camera.allCamerasCount); -
allCameras 得到场景中所有已启用的摄像机 Camera[] allCameras = Camera.allCameras;
print(allCameras.Length);
-
渲染相关委托
静态变量 说明 示例代码
onPreCull 摄像机开始剔除前触发的事件 Camera.onPreCull += (c) => { /* 处理逻辑 */ };
onPreRender 摄像机开始渲染前触发的事件 Camera.onPreRender += (c) => { /* 处理逻辑 */ };
onPostRender 摄像机完成渲染后触发的事件 Camera.onPostRender += (c) => { /* 处理逻辑 */ };
重要成员
成员 说明 示例代码 注意事项
depth 设置摄像机渲染深度 Camera.main.depth = 10; -
WorldToScreenPoint 世界坐标转屏幕坐标(血条功能) Vector3 v = Camera.main.WorldToScreenPoint(this.transform.position);
print(v);
-
ScreenToWorldPoint 屏幕坐标转世界坐标(需设置 Z 值) Vector3 v = Input.mousePosition;
v.z = 5;
sphere.position = Camera.main.ScreenToWorldPoint(v);
不设置 Z 值时默认为 0,设置后是摄像机前方对应单位的坐标

Light 光面板

光源组件

分类 参数 说明 示例或注意事项
光源类型 Directional(方向光) 模拟太阳,光照方向一致 -
Spot(聚光灯) 类似手电筒,需设置 Range 和 Spot Angle 需设置 Range(范围)和 Spot Angle(光锥角度)
Point(点光源) 类似小灯泡,向四周发光 -
Area(面光源) - -
光源颜色和模式 Color(光源颜色) 设置光源颜色 -
Mode(光源模式) Realtime(实时光源,性能消耗大);Baked(烘焙光源,无法动态变化);Mixed(混合光源) 根据性能和效果需求选择模式
光源强度和间接系数 Intensity(光源强度) 控制光源亮度 -
Indirect Multiplier(间接系数) 改变间接光强度,低于 1 每次反弹光更暗,大于 1 更亮 -
阴影类型 Shadow Type None(关闭);Hard(生硬);Soft(柔和);Realtime Shadows(实时) 选择阴影类型提升视觉效果
Strength(强度) 阴影暗度(0-1,越大越黑) -
Resolution(分辨率) 阴影贴图分辨率,越高越逼真 -
Bias(偏离) 阴影推离光源的距离 -
Normal Bias(法线偏离) 阴影投射面沿法线收缩距离 -
Near Panel(近平面) 渲染阴影的近裁剪面 -
剪影和效果 Cookie(剪影) 投影遮罩,一般用于聚光灯显示图案 -
Cookie Size(剪影大小) 控制剪影大小 -
Draw Halo(绘制光晕) 球形光环开关,用于蜡烛等效果 需在摄像机上加 FlareLayer 脚本才能在 Game 窗口看到
Flare(眩光) 耀斑效果,类似太阳耀斑 需在摄像机上加 FlareLayer 脚本才能在 Game 窗口看到
渲染模式和剔除遮罩 Render Mode Auto(自动);Important(重要,效果好消耗大);Not Important(非重要) 根据性能和效果需求选择
Culling Mask(剔除遮罩) 决定哪些层的对象受到该光源影响 -
代码控制 intensity 控制光的强度乘以光颜色 light.intensity = 0.5f;

光面板(照明设置)

分类 参数 说明 示例或注意事项
环境相关设置 Skybox Material(天空盒材质) 改变天空盒,需创建天空盒着色器材质 -
Sun Source(太阳来源) 不设置会默认使用场景中最亮的方向光 -
环境光设置 Source(环境光光源颜色) Skybox(天空盒);Gradient(渐变,可单独设置天空、地平线、地面颜色) -
Intensity Multiplier(环境光亮度) 控制环境光亮度 -
Ambient Mode(环境模式) 全局光照模式,Realtime(已弃用)、Baked(烘焙) 需启用实时全局和全局烘焙
其它设置 Fog(雾开关) 控制雾的显示 -
Color(雾颜色) 设置雾的颜色 -
Mode(雾计算模式) Linear(线性);Exponential(指数);Exponential Square(指数平方) 不同模式需设置不同参数(如 Linear 需设置 Start 和 End 距离)
Halo Texture(光晕材质) 光源周围光环的纹理 -
Halo Strength(光晕强度) 光环可见性 -
Flare Fade Speed(炫光交叉淡化速度) 耀斑淡出时间 -
Flare Strength(炫光强度) 耀斑可见性 -
Spot Cookie(聚光灯剪影) 聚光灯剪影纹理 -

物理系统 - 刚体

刚体组件参数

英文参数 说明 示例或注意事项
Mass(质量) 默认为千克,质量越大惯性越大 -
Drag(空气阻力) 根据力移动对象时的空气阻力大小,0 表示无阻力 -
Angular Drag(角阻力) 阻碍对象旋转的阻力,越大越不容易旋转 -
Use Gravity(重力开关) 是否受重力影响 -
Is Kinematic 开启后不受力影响,只能通过 Transform 移动 -
Interpolate(插值运算) 让刚体移动更平滑 可更改 FixTime,开启插值运算可平滑移动
None(无插值) 不应用插值运算
Interpolate(插值模式) 根据前一帧变换平滑变换
Extrapolate(外推模式) 根据当前速度预测刚体位置
Collision Detection(碰撞检测) 防止快速移动对象穿过其它对象 -
Discrete(离散检测) 默认模式,适合一般速度物体,性能最优
Continuous(连续检测) 适合高速物体,性能消耗较高
Continuous Dynamic(连续动态检测) 适合快速移动物体与静止物体碰撞,性能消耗高
Continuous Speculative(连续推测检测) 预测物体位置进行碰撞检测,性能较高
Constraints(刚体约束) 对刚体运动的限制 -
Freeze Position(冻结位置) 停止刚体沿 X、Y、Z 轴的移动
Freeze Rotation(冻结旋转) 停止刚体围绕 X、Y、Z 轴旋转
Info(当前刚体信息) - -

刚体参数和方法

  • 获取刚体组件rigidBody = this.GetComponent<Rigidbody>();
  • AddForce 方法:相对世界坐标添加力,如 rigidBody.AddForce(Vector3.forward * 10);;相对自身朝向移动用 rigidBody.AddForce(this.transform.forward * 10);
  • AddRelativeForce 方法:相对本地坐标添加力,如 rigidBody.AddRelativeForce(Vector3.forward * 10);
  • AddTorque 方法:相对世界坐标添加扭矩力,如 rigidBody.AddTorque(Vector3.up * 10);
  • AddRelativeTorque 方法:相对本地坐标添加扭矩力,如 rigidBody.AddRelativeTorque(Vector3.up * 10);
  • velocity 变量:设置刚体速度,如 rigidBody.velocity = Vector3.forward * 5;
  • AddExplosionForce 方法:模拟爆炸效果,参数为(力的大小,中心,半径),如 rigidBody.AddExplosionForce(100, Vector3.zero, 10);
  • 力的模式(ForceMode)
    • Acceleration:加速度模式,忽略质量。
    • Force:力模式,与质量有关。
    • Impulse:冲击力模式,瞬间力。
    • VelocityChange:瞬时速度模式,忽略质量。
  • 恒力场组件:搜索 Constant Force 添加到物体,无需代码即可保持力。
  • 刚体的休眠:使用 IsSleeping() 判断是否休眠,WakeUp() 唤醒刚体。

物理系统 - 碰撞体

3D 碰撞器种类

  • 盒状碰撞器 (Box Collider)
  • 球状碰撞器 (Sphere Collider)
  • 胶囊碰撞器 (Capsule Collider)
  • 网格碰撞器 (Mesh Collider)
  • 轮胎碰撞器 (Wheel Collider)
  • 地形碰撞器 (Terrain Collider)

3D 碰撞器共同参数

英文参数 说明 示例或注意事项
Edit Collider 改变碰撞体大小 -
Is Trigger 启用后为触发器,忽略物理碰撞 -
Material 确定碰撞时的交互方式 -
Center 碰撞体在对象局部空间的中心点 -

常用碰撞器

碰撞器类型 英文参数 说明
Box Collider Size(大小) 碰撞体在 X、Y、Z 方向的大小
Sphere Collider Radius(半径) 球形碰撞体的半径大小
Capsule Collider Radius(半径) 胶囊体的半径
Height(高度) 胶囊体的高度
Direction(轴向) 胶囊体在对象局部空间的轴向

说明:异形物体可使用多种碰撞器组合。刚体对象的子对象碰撞器会参与碰撞检测(如金字塔预设体,仅在最高层级对象添加刚体,子对象的碰撞器仍生效)。

不常用碰撞器

碰撞器类型 英文参数 说明 示例或注意事项
Mesh Collider - 性能消耗较高,默认不显示碰撞器边框,开启 Convex 才显示 加了刚体的网格碰撞器必须开启 Convex 才能碰撞
Convex(凸面) - -
Cooking Options 网格烹制选项 -
Mesh(网格模型) 引用用于碰撞的网格 -
Wheel Collider - 国内赛车游戏公司较少使用 给车的父对象加刚体,子对象加车轮碰撞器模拟汽车
Mass(车轮质量) - -
Radius(车轮半径) - -
Wheel Damping Rate 车轮阻尼值 -
Suspension Distance 车轮悬架最大延伸距离 -
Force App Point Distance 车轮受力点 -
Suspension Spring 悬架弹簧力和阻尼力 -
Terrain Collider - 性能消耗较高 -
Terrain Data 地形数据 -
Enable Tree Colliders 启用树碰撞体 -

物理系统 - 物理材质

英文参数 说明
Dynamic Friction(动摩擦力) 已移动时使用的摩擦力,0 到 1 之间,0 像冰,1 使对象迅速静止
Static Friction(静摩擦力) 静止时使用的摩擦力,0 到 1 之间,0 像冰,1 难以移动
Bounciness(弹性) 表面弹性,0 不反弹,1 无能量损失
Friction Combine(摩擦力组合) 两个碰撞对象摩擦力的组合方式:Average(平均值)、Minimum(最小值)、Maximum(最大值)、Multiply(相乘)
Bounce Combine(反弹组合) 两个碰撞对象弹性的组合方式,模式与摩擦力组合相同

碰撞检测函数

碰撞器与触发器的核心条件对比

碰撞发生的必要条件
条件 说明 示例
至少1个刚体 提供物理模拟动力源 下落的立方体(带刚体)碰撞地面(无刚体但有碰撞器)
双方均有碰撞器 定义碰撞体积 子弹(刚体+碰撞器) vs 敌人(碰撞器)
碰撞器未开启 Is Trigger 必须为物理碰撞模式 关闭触发器的胶囊体碰撞
触发器触发的必要条件
条件 说明 示例
至少1个碰撞器开启 Is Trigger 标记为触发器,禁用物理碰撞 门的触发区域(碰撞器+Is Trigger)
至少1个刚体(可选) 非必须,但刚体存在时事件更稳定 玩家(刚体)进入触发器区域(无刚体的碰撞器)
双方碰撞器重叠 空间上产生交集 球形触发器包裹玩家

物理碰撞检测响应函数

// 碰撞触发接触时执行
private void OnCollisionEnter(Collision collision)
{
    Collider collider = collision.collider; // 碰撞对象的碰撞器
    GameObject gameObject = collision.gameObject; // 碰撞对象
    Transform transform = collision.transform; // 碰撞对象的位置
    
    int contactCount = collision.contactCount;
    ContactPoint[] pos = collision.contacts; // 接触点数组
    
    print(this.name + "被" + collision.gameObject.name + "撞到了");
}

// 碰撞结束分离时执行
private void OnCollisionExit(Collision collision)
{
    print(this.name + "被" + collision.gameObject.name + "结束碰撞了");
}

// 碰撞持续接触时执行(静止时不调用)
private void OnCollisionStay(Collision collision)
{
    print(this.name + "一直在和" + collision.gameObject.name + "接触");
}

触发器检测响应函数

// 触发开始时执行
protected virtual void OnTriggerEnter(Collider other)
{
    print(this.name + "被" + other.gameObject.name + "触发了");
}

// 触发结束时执行
private void OnTriggerExit(Collider other)
{
    print(this.name + "被" + other.gameObject.name + "结束触发状态了");
}

// 触发持续时执行
private void OnTriggerStay(Collider other)
{
    print(this.name + "和" + other.gameObject.name + "正在触发");
}

Unity 音效系统

音频文件导入

分类 知识点 说明/示例
支持格式 WAV、MP3、OGG、AIFF 推荐 WAV(无损)用于短音效,MP3/OGG 用于长音频
导入操作 直接拖拽到 Project 窗口 -
属性设置 Force To Mono(强制单声道) 多声道转单声道,适合语音类音频
LoadType(加载类型) Decompress On Load(小音效,内存高);Compress in Memory(大音效,内存低);Streaming(极长音频)
Preload Audio Data(预加载) 勾选:进入场景预加载;不勾选:首次播放时加载
预览与控制 底部工具栏播放/暂停/循环按钮 支持拖拽进度条预览音频

音频源(AudioSource)

音频源组件参数
分类 参数 说明 适用场景 注意事项
基础设置 AudioClip 拖拽音频文件,指定播放内容 背景音乐、UI 音效、技能特效 -
Play On Awake 启用时对象创建即播放(默认√) 背景音乐(√)、UI 点击音效(×) 动态生成对象需关闭此选项
Loop 循环播放(默认×) 背景音乐、环境音 短音效禁用循环
音量控制 Volume 音量(0-1,支持负数) 主音量调节、角色音量衰减 结合 PlayerPrefs 存储用户设置
Priority 优先级(0-255,0 最高,默认 128) 多音效冲突时高优先级优先播放 超过 32 个音效可能爆音
2D 音效 Stereo Pan 左右声道平衡(-1左 ~ 1右) UI 按钮立体声、2D 游戏音效 与 Spatial Blend=0 配合使用
3D 音效 Spatial Blend 空间混合(0=2D,1=3D) 3D 游戏脚步声、NPC 语音 设为 1 时需配置 Min/Max Distance 和衰减曲线
Doppler Level 多普勒效果(0-1,模拟运动音调变化) 车辆引擎声、飞行物音效 角色移动时生效,静态对象设为 0
Volume Rolloff 衰减模式:Logarithmic(真实)、Linear(线性)、Custom(自定义) 脚步声(Logarithmic)、环境音(Custom) Custom 需手动绘制曲线
Min/Max Distance 3D 音效生效范围 脚步声(Min=1,Max=5)、BOSS 语音(Min=2,Max=10) Min 过小、Max 过大影响性能
性能控制 Bypass Effects 跳过音效滤镜(如混响、延迟) 性能优化,禁用非必要特效 仅在低端设备或复杂场景使用
Output 输出到混音器(高级功能) 多声道混音、分组控制 需配合 AudioMixer 组件使用
音频源参数和方法
方法/属性 说明 示例代码
Play() 播放音频(从开头) audioSource.Play();
PlayDelayed(5f) 延迟播放(秒为单位) audioSource.PlayDelayed(2f);
Pause()/UnPause() 暂停/恢复(保留播放位置) audioSource.Pause();
Stop() 停止并重置位置 audioSource.Stop();
isPlaying 检测是否播放(只读) if (!audioSource.isPlaying) 播放完毕逻辑;
多 AudioSource 一个物体挂多个音频源,独立控制 AudioSource[] audios = GetComponents<AudioSource>(); audios[1].Play();

麦克风录制

功能 方法/属性 示例代码
获取设备 Microphone.devices string[] mics = Microphone.devices;
开始录制 Microphone.Start(设备名, 循环, 时长, 采样率) audioClip = Microphone.Start(null, false, 10, 44100);
停止录制 Microphone.End(设备名) Microphone.End(null);
获取音频数据 AudioClip.GetData(数组, 起始样本) float[] data = new float[clip.channels * clip.samples];
clip.GetData(data, 0);
播放录音 绑定 AudioSource 播放 audioSource.clip = 录音Clip; audioSource.Play();

36.3 面试题精选

基础题

1. Unity 工程中 Assets 与 ProjectSettings 各自存什么?删错会怎样?

题目

请说明 AssetsProjectSettings 在项目目录里的大致职责;若只删其中一类文件夹,工程通常还能否打开,可能有什么后果?

深入解析
  • Assets:工程内的资源与脚本入口,是你在 Project 窗口中管理的主要内容;删除后需重新导入或还原,否则场景与资源引用会丢失。
  • ProjectSettings:项目级设置(如部分标签、图层、Player/Quality 等配置)的落盘位置;与 Assets 同级。正文强调删除可能导致部分设置丢失
  • 正文还提到:除 Assets 外的生成文件夹删掉后工程往往仍能打开,但会触发重新生成/重新加载;ProjectSettings 被删则自定义标签、图层等可能丢失
答题示例

Assets 放资源与脚本,是编辑器主要编辑内容;ProjectSettings 存项目级配置。

只删部分缓存类文件夹有时还能打开工程但会重算;删 ProjectSettings 容易导致标签、图层等设置丢失,需谨慎。

参考文章
  • 2.Unity环境搭建
  • 6.Unity界面基础-工具栏和父子关系

2. 为什么 Inspector 能显示脚本字段?SerializeField 和 public 各解决什么问题?

题目

Unity 如何在 Inspector 中显示挂载脚本上的字段?[SerializeField]public 在「能在 Inspector 上编辑」这件事上各是什么角色?

深入解析
  • 引擎通过 反射 读取脚本类型上的可序列化字段,再在 Inspector 中生成控件;类名与文件名一致等约定便于定位类型信息(见 7.Unity工作原理-反射机制和游戏场景)。
  • public:默认序列化并在 Inspector 显示(除非 [HideInInspector])。
  • [SerializeField]:让 private/protected 等本不对外暴露的字段仍参与序列化并在 Inspector 显示,兼顾封装与调试/策划可调参。
答题示例

Inspector 依赖序列化与反射把字段变成可编辑控件。

public 默认可序列化显示;[SerializeField] 用来让私有/保护字段也能序列化并显示,常用在不想对外公开字段名的同时要在面板上调参。

参考文章
  • 7.Unity工作原理-反射机制和游戏场景
  • 11.Unity脚本基础-Inspector窗口可编辑的变量

3. 预设体实例上的 Overrides、Apply、Unpack 分别是什么操作?

题目

场景里的 Prefab 实例被改到与磁盘上的 Prefab 不一致时,Inspector 会出现覆盖相关 UI。请说明 Apply(应用到 Prefab)UnpackUnpack Completely 与「仅改当前实例」之间的典型区别。

深入解析
  • 实例覆盖:只影响当前场景中的实例,不写入源 Prefab。
  • Apply / 覆盖到 Project:把当前实例上的改动写回 Prefab 资源,通常会影响所有引用该 Prefab 的实例(除非走变体等进阶流程,入门篇以「同步到所有实例」心智为主)。
  • Unpack:实例与 Prefab 断开关联,层级上父级变为普通对象(子级若仍是 Prefab 可保留子 Prefab)。
  • Unpack Completely:递归解除,整棵子树都不再与各自 Prefab 关联。
答题示例

实例改动可先只留在场景里;点 Apply 会把改动写回磁盘上的 Prefab,影响其它引用。

Unpack 是解除一层关联,Unpack Completely 是整棵都拆成普通对象,适合不再做 Prefab 管理的物体。

参考文章
  • 8.Unity工作原理-预设体和资源包的导入导出

4. GameObject.Find 类 API 的共性限制与性能风险?

题目

GameObject.FindFindWithTagFindObjectOfType 等查找方法有哪些共同限制?为何不建议在 Update 里频繁调用?

深入解析
  • 正文强调:只能找到激活对象,找不到失活对象。
  • 多个对象同名或同 Tag 时,无法保证找到哪一个(单对象查找)。
  • Find 遍历场景对象;FindObjectOfType 还要遍历组件,成本更高
  • 因此适合在初始化时缓存引用,避免每帧全场景搜索。
答题示例

这些查找基本都只扫激活对象,且多匹配时结果不确定。

Find / FindObjectOfType 代价高,应缓存引用,别在 Update 里每帧 Find。

参考文章
  • 14.Unity重要组件和API-GameObject

5. Time.deltaTimeTime.unscaledDeltaTime 何时选用?

题目

游戏暂停(timeScale = 0)时,若仍希望某段位移或 UI 动画继续按真实时间推进,应使用哪个帧间隔?与 deltaTime 的差别是什么?

深入解析
  • deltaTime timeScale 影响,暂停时为 0,适合「随游戏时间暂停」的移动。
  • unscaledDeltaTime 不受 timeScale 影响,适合暂停菜单动画、不受暂停影响的相机/UI 等。
  • 正文示例:timeScale 改变时,deltaTimeunscaledDeltaTime 的比值关系可用于理解二者差异。
答题示例

暂停后还想动,用 unscaledDeltaTime;希望跟游戏时间一起停,用 deltaTime

参考文章
  • 15.Unity重要组件和API-Time

6. Screen.currentResolutionScreen.width / Screen.height 有何区别?

题目

做 UI 或按像素布局时,应优先用哪一组尺寸?currentResolution 与 Game 窗口宽高分别对应什么?

深入解析
  • currentResolution:当前显示器分辨率(Resolution),不是 Game 视图画布大小。
  • Screen.width / height:当前 Game 窗口的像素宽高,代码里按「玩家看到的游戏画面」计算时通常用它们。
答题示例

currentResolution 是显示器;Screen.width/height 是 Game 窗口。跟游戏画面相关的布局用后一组。

参考文章
  • 22.Unity重要组件和API-Screen

7. 使用 Camera.main 的前提与常见坑?

题目

Camera.main 在什么条件下可用?场景里多个带 MainCamera 标签的相机会怎样?

深入解析
  • 需要场景中存在 tag 为 MainCamera启用的摄像机,否则为 null 或报错(正文)。
  • 多个 MainCamera 时,获取结果不确定是哪一个,应避免。
答题示例

必须有一个启用的主摄且 tag 正确;多个 MainCamera 时 main 指代不稳定,应改显式引用。

参考文章
  • 24.Unity重要组件和API-Camera代码控制

进阶题

1. 场景文件 .unity 本质上是什么?把别的场景拖进当前场景一般做什么?

题目

请说明 .unity 场景文件在磁盘上的本质;编辑器里把另一个场景拖入当前场景,常见用途是什么?

深入解析
  • 正文:.unity特殊格式的配置文件,保存场景设置、场景中的对象及组件等信息。
  • 多场景叠加:把别的场景拖进当前场景,主要用于 把其它场景里的对象拿到当前场景 使用,一般不常用
答题示例

.unity 本质是文本/序列化配置,描述场景与对象状态。

拖入其它场景多半是为了把其中的对象合并到当前场景继续编辑,属于临时搬运,不是常规关卡流程的唯一方式。

参考文章
  • 7.Unity工作原理-反射机制和游戏场景

2. Awake、OnEnable、Start 的调用时机与大致顺序?

题目

同一对象上挂载的脚本里,AwakeOnEnableStart 分别在什么时机被调用?对象从失活到激活时,哪些会再次触发?

深入解析
  • Awake:脚本/对象创建时,类似「初始化入口」,早于首次帧更新前的 Start
  • OnEnable:对象激活时调用;运行开始时若默认激活会调用一次。
  • Start第一次帧更新之前执行,比 Awake
  • OnDisable / OnDestroy:失活、销毁时;销毁前会先失活,故先 OnDisableOnDestroy(与正文一致)。
答题示例

同一对象上通常是 Awake → OnEnable(若激活)→ Start(首次帧前)。

对象被 SetActive(false) 再打开会再走 OnEnable,Awake 只来一次。

参考文章
  • 10.Unity脚本基础-生命周期函数

3. GetComponentInChildren 的 includeInactive 何时要设为 true?

题目

GetComponentInChildren<T>(bool includeInactive = false) 中第二个参数为 true 时与默认 false 有何区别?什么业务场景需要传 true

深入解析
  • false(默认):子对象未激活不会在该子对象上查找组件。
  • true:即使子对象 inactive 也会参与查找。
  • 适用:逻辑里常把子物体先隐藏,但仍需通过代码取到其上脚本(如池、预置隐藏的特效节点)。
答题示例

默认 false 会跳过失活子物体上的组件;需要操作「隐藏但仍存在」的子节点时传 true。

参考文章
  • 12.Unity脚本基础-MonoBehaviour中的重要内容-基础属性和组件的获取

4. DestroyDestroyImmediate 有何区别?为何优先 Destroy

题目

删除游戏对象时,DestroyDestroyImmediate 在执行时机和对卡顿的影响上有何不同?正文推荐默认用哪一个?

深入解析
  • Destroy异步,本帧打标记,通常下一帧真正移除,降低单帧尖刺。
  • DestroyImmediate同步立即从内存移除,可能造成卡顿;文档亦建议优先 Destroy
  • 仅在编辑器脚本或特殊必须立即释放的场景再考虑 DestroyImmediate
答题示例

Destroy 是延迟销毁,更平滑;DestroyImmediate 立刻删,容易卡帧。

游戏运行时一般优先 Destroy。

参考文章
  • 14.Unity重要组件和API-GameObject

5. positionlocalPosition 何时与 Inspector 上看到的「一致」?

题目

什么情况下 transform.position 与面板上的位置读数会一致?何时应以 localPosition 为准?

深入解析
  • 无父对象父对象在世界原点时,positionlocalPosition 往往与面板局部读数对齐关系更简单。
  • 有父对象且父已偏移/旋转时,世界坐标 position本地坐标 localPosition 一般不同;若要以面板局部坐标改物体,应改 localPosition(正文强调)。
答题示例

无父或父在原点时二者关系简单;有父物体时世界坐标和本地坐标分离,对齐 Inspector 局部应用 localPosition。

参考文章
  • 16.Unity重要组件和API-Transform位置和位移

6. Transform.FindGameObject.Find 在范围与失活对象上的差异?

题目

transform.Find("子物体名")GameObject.Find("名字") 相比,各自搜索范围是什么?谁能找到失活对象?

深入解析
  • GameObject.Find全场景按名字,仅激活对象
  • Transform.Find:仅在当前 Transform 的直接子级按名字查找,找不到孙子;但可以找到失活的子对象(正文多次强调与 GameObject 查找的对比)。
答题示例

GameObject.Find 扫全场景只要激活的;Transform.Find 只查直接子节点,但能查到失活子物体。

参考文章
  • 19.Unity重要组件和API-Transform父子关系

7. 多摄像机叠加时,DepthClear Flags(如 Depth only)如何配合?

题目

两个摄像机要同时贡献画面(例如一个画 3D、一个画 UI 或不同层)时,渲染顺序与 Clear Flags、Culling Mask 通常怎么配?

深入解析
  • Depth 越大越后渲染,后渲染的会叠在先渲染的之上(正文)。
  • 上层摄像机常选 Depth only,只清深度、背景透明,再配合 Culling Mask 只渲染需要的层,实现叠加。
  • Viewport Rect 可做分屏(0~1 比例划分 Game 视图)。
答题示例

低 Depth 先画全屏或底图,高 Depth 用 Depth only 只画自己那一层,避免把底下全清掉。

参考文章
  • 23.Unity重要组件和API-Camera参数

8. 物理「碰撞回调」与「触发器回调」分别在什么条件下触发?

题目

OnCollisionEnterOnTriggerEnter 各自要求碰撞器、刚体、Is Trigger 处于什么状态?表现上有何不同?

深入解析
  • 物理碰撞:双方有碰撞器、至少一方有刚体,且 Is Trigger 关闭,会有力的响应;回调为 OnCollision*,参数为 Collision
  • 触发器:至少一方碰撞器 Is Trigger 开启,通常无物理阻挡,只走 OnTrigger*,参数为 Collider
  • 回调挂在带刚体的父物体上才能正确收到(正文强调子物体挂脚本收不到的情况)。
答题示例

真撞用 Collision,要穿过去只检测用 Trigger;触发器不产生常规物理挤压。

参考文章
  • 30.核心系统-物理系统-碰撞检测函数

9. Rigidbody.isKinematic 开启后行为如何?

题目

勾选 Is Kinematic 后,刚体还受力和重力吗?位移应通过什么方式驱动?常见用途?

深入解析
  • 不受物理引擎力/重力驱动,只能Transform(或动画)去动(正文)。
  • 适合移动平台、由程序完全控制轨迹的物体,或需动画驱动又参与某些物理查询的场景。
答题示例

Kinematic 等于告诉物理「别推我」,位置自己用 Transform 改;仍可有碰撞器参与检测,但不按动力学积分。

参考文章
  • 27.核心系统-物理系统-刚体

深度题

1. 脚本执行顺序(Script Execution Order)解决什么问题?滥用会怎样?

题目

Unity 中同一帧内多个脚本都可能写 Awake/Start/Update,默认顺序不确定时可能产生依赖问题。请说明 Script Execution Order 如何工作,以及项目中应如何克制使用。

深入解析
  • Edit → Project Settings → Script Execution Order(或等价入口)中为脚本指定 order 数值,越小越先执行(见 9.Unity脚本基础-脚本基本规则)。
  • 用途:在无法通过显式引用、事件拆分解决的初始化顺序问题时,作为最后手段固定顺序。
  • 风险:全局顺序表难维护,跨模块耦合加重;更好的做法是减少跨脚本初始化依赖、用显式调用、事件或单入口初始化。
答题示例

执行顺序表给脚本一个全局优先级,数越小越早跑 Awake/Start 等。

适合救急依赖顺序问题,但长期依赖会让模块耦合变差,应配合架构拆分减少硬顺序。

参考文章
  • 9.Unity脚本基础-脚本基本规则

2. FixedUpdate 与 Update、物理帧之间是什么关系?

题目

请说明 FixedUpdateUpdate 的区别;为什么刚体受力通常写在 FixedUpdate 里;Time.fixedDeltaTime 与游戏帧 deltaTime 为何可能不一致?

深入解析
  • Update:每游戏帧调用,帧率波动时调用间隔变化。
  • FixedUpdate:每 固定时间步调用,用于与物理模拟同步;步长可在 Project Settings → Time 中配置(正文与示例代码注释)。
  • 刚体模拟在固定步长上积分,故对刚体施加力、改 velocity 等通常放 FixedUpdate,避免与帧率绑定导致不稳定。
  • Time.deltaTimetimeScale 等影响;物理步长由 fixedDeltaTime 等控制,与渲染帧不同步。
答题示例

Update 跟显示器帧走,FixedUpdate 跟物理固定步长走。

施力、改刚体速度用 FixedUpdate;deltaTime 是帧间隔,fixedDeltaTime 是物理步长,二者不必相等。

参考文章
  • 10.Unity脚本基础-生命周期函数

3. SetParentworldPositionStays 为 true 或 false 时分别发生什么?

题目

transform.SetParent(新父, worldPositionStays) 第二个参数为 truefalse 时,子物体在场景中的世界位置与 Inspector 本地坐标分别如何变化?

深入解析
  • true:尽量保持世界空间下的位置、旋转、缩放不变,重新计算相对新父的本地变换。
  • false:不保留世界状态,把当前世界坐标下的变换直接写入本地坐标(正文描述为「粗暴」赋到面板上),物体在世界里可能跳变。
答题示例

true 保持世界里看起来不动,只改父子关系;false 可能让本地坐标被直接覆盖,视觉上容易跳。

参考文章
  • 19.Unity重要组件和API-Transform父子关系

4. TransformPointTransformDirectionTransformVector 在「是否受缩放影响」上如何区分?

题目

本地转世界时,何时用 TransformPoint?方向类 API 中 Direction 与 Vector 为何一个不受缩放影响、一个受缩放影响?

深入解析
  • TransformPoint:处理本地空间中的点(位置),受缩放影响,用于「面前 N 米生成物体」等。
  • TransformDirection:方向向量,不受缩放(只旋转)。
  • TransformVector:表示带缩放意义的向量变换,受缩放影响。
  • 世界转本地有对应的 InverseTransform* 三组(正文表格与示例)。
答题示例

点用 Point,带缩放;纯朝向用 Direction,不受缩放;需要缩放进度的位移用 Vector。

参考文章
  • 20.Unity重要组件和API-Transform坐标转换

5. Input.GetAxisInput.GetAxisRaw 的区别与典型用法?

题目

虚拟轴输入中,GetAxisGetAxisRaw 返回值有何不同?分别适合什么操作手感?

深入解析
  • GetAxis:带平滑/渐变,可在 -1~1 间出现小数,适合需要加速缓冲的相机、载具移动。
  • GetAxisRaw无平滑,仅 -1、0、1,适合需要立即响应的离散操作(如技能是否按下,原文以 Fire1 为例)。
答题示例

GetAxis 有过渡更顺滑;GetAxisRaw 只有三态,适合要明确开关感的操作。

参考文章
  • 21.Unity重要组件和API-Input

6. ScreenToWorldPoint 里为什么要改 z?和 Physics.Raycast 选点的思路差异?

题目

Camera.main.ScreenToWorldPoint(Input.mousePosition) 前为何常要给 z 赋非零值?z 的几何含义是什么?

深入解析
  • 鼠标 Screen 坐标 z 默认为 0;直接转换会得到近平面附近的一点,深度信息不足。
  • 设置 z 为到摄像机的距离(世界单位),得到的是沿摄像机前方、该深度处的世界坐标点(正文「横截面」心智)。
  • 精确贴地/贴物更常用 Raycast;ScreenToWorldPoint 适合固定深度平面上的跟随等。
答题示例

z 表示离相机多远,不设就都在近裁平面附近一团。要贴场景表面一般用射线。

参考文章
  • 24.Unity重要组件和API-Camera代码控制

7. ForceMode.AccelerationForceImpulseVelocityChange 如何选用?

题目

Rigidbody.AddForce 的第二个参数几种模式,与质量、是否按时间步累积的关系大致怎样?各举一个适用场景。

深入解析
  • Acceleration:加加速度,忽略质量,同等力下轻重物体更易获得相近线加速度。
  • Force:持续力,与质量有关(F=ma 心智)。
  • Impulse:瞬时冲量,与质量有关,适合爆炸、单次击打。
  • VelocityChange:瞬时改速度,忽略质量
  • 具体数值与 FixedUpdate 步长结合(正文动量示例)。
答题示例

持续推用 Force;要无视质量用 Acceleration;一下撞飞用 Impulse;直接设速度差用 VelocityChange。

参考文章
  • 31.核心系统-物理系统-刚体加力

8. 场景中 AudioListenerSpatial Blend 分别要解决什么问题?

题目

AudioListener 一般挂在哪里、同一活跃场景允许多个吗?Spatial Blend 从 0 到 1 变化代表什么?

深入解析
  • AudioListener 相当于耳朵,通常挂在主摄像机;工程里一般只保留一个启用的 Listener(多摄像机时新建相机会自带组件,需避免重复,正文以主摄为默认挂载点)。
  • Spatial Blend:0 为 2D(不受空间距离衰减),1 为 3D(受距离与 3D 设置影响),中间为混合。
答题示例

Listener 一个场景一个耳朵,常挂主摄。Spatial Blend 控制从纯 2D UI 声到 3D 空间声的过渡。

参考文章
  • 33.核心系统-音效系统-音频源和音频监听脚本


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏