目录
- 一、Unity入门
- 二、Unity基础
- 三、Unity核心
- 四、Unity进阶
一、Unity入门
1 生命周期函数和打印信息
1.1. 生命周期函数详解
函数名 | 调用时机 | 用途 |
---|---|---|
Awake | 对象(脚本类对象)被创建时调用 | 类似构造函数,可进行对象创建时的初始化操作 |
OnEnable | 对象被激活时调用 | 可在此处编写对象激活时的逻辑处理代码,运行游戏时,因脚本挂载对象默认激活,会自动调用一次 |
Start | 对象进行第一次帧更新之前执行 | 用于编写初始化信息的逻辑,执行时间比 Awake 晚 |
FixedUpdate | 每一物理帧执行 | 主要用于进行物理更新,物理帧和游戏帧不同 |
Update | 每一游戏帧执行 | 用于处理游戏核心逻辑更新 |
LateUpdate | 比 Update 晚执行 | 一般用于处理摄像机位置更新相关内容 |
OnDisable | 对象失活时调用 | 可在此处编写对象失活时的处理逻辑 |
OnDestroy | 对象被销毁时调用 | 销毁对象时调用,调用前对象失活,也会调用一次 OnDisable |
1.2. 在 Unity 中打印信息
类 | 方法 | 用途 |
---|---|---|
Debug 类 | Log 方法 | 打印普通信息,如 Debug.Log("Awake Debug.Log"); |
Debug 类 | LogWarning 方法 | 打印警告信息,如 Debug.LogWarning("Awake Debug.LogWarning"); |
Debug 类 | LogError 方法 | 打印报错信息,如 Debug.LogError("Awake Debug.LogError"); |
MonoBehaviour 类 | print 方法 | 继承 MonoBehaviour 类时,可使用该方法打印普通信息,如 print("Awake print"); |
2 Unity 特性
2.1变量可见性控制
特性 | 作用 | 适用变量 | 语法 | 关键说明 |
---|---|---|---|---|
[SerializeField] | 强制私有/保护变量显示在 Inspector | private /protected 变量 | [SerializeField] private int value; | - 序列化字段,支持基本类型、数组、GameObject 等- 运行时修改会影响成员变量 |
[HideInInspector] | 隐藏公共变量(避免误操作) | public 变量 | [HideInInspector] public int value; | - 代码中可访问,但 Inspector 不显示 |
默认公共变量 | 直接显示(无需特性) | public 变量 | public int value; | - 简单直接,但暴露所有公共字段 |
2.2.自定义类型序列化
类型 | 显示条件 | 示例 | 关键说明 |
---|---|---|---|
枚举 | 直接显示(无需额外特性) | public E_TestEnum enumValue; | - 下拉菜单选择枚举值 |
结构体 | 需 [System.Serializable] 特性 | [Serializable] public struct MyStruct{...} | - 序列化后可展开编辑字段 |
类 | 需 [System.Serializable] 特性 + 继承 UnityEngine.Object 或标记为 [CreateAssetMenu] | [Serializable] public class MyClass{...} | - 非 MonoBehaviour 需手动序列化- ScriptableObject 需 [CreateAssetMenu] |
集合 | 直接显示(数组、List<T> ) | public int[] array; public List<int> list; | - 支持动态添加/删除元素(List 需初始化) |
2.3辅助特性(提升可读性)
特性 | 作用 | 参数 | 示例 |
---|---|---|---|
[Header("标题")] | 分组标题(字段上方显示) | 字符串(如 "基础属性" ) | [Header("战斗属性")] public int atk; |
[Tooltip("提示")] | 悬停提示(鼠标悬停显示说明) | 字符串(如 "最大生命值" ) | [Tooltip("闪避率")] public float miss; |
[Space(像素)] | 字段间隔(垂直空白) | 可选像素值(默认 10) | [Space(20)] public int crit; |
[Range(Min, Max)] | 数值滑条(限制输入范围) | 最小值,最大值(如 0, 100 ) | [Range(0, 10)] public float luck; |
[Multiline(行数)] | 多行文本框(固定行数) | 可选行数(默认 3) | [Multiline(5)] public string tips; |
[TextArea(Min, Max)] | 滚动文本框(超过最大行数显示滚动条) | 最小行数,最大行数(如 3, 5 ) | [TextArea(3, 4)] public string desc; |
2.4交互增强特性
特性 | 作用 | 参数 | 示例 |
---|---|---|---|
[ContextMenuItem("按钮名", "方法")] | 为变量添加右键快捷方法(无参无返回) | 按钮文本,方法名 | [ContextMenuItem("重置", "ResetMoney")] public int money; |
[ContextMenu("按钮名")] | 为方法添加 Inspector 执行按钮(非静态无参) | 按钮文本 | [ContextMenu("测试逻辑")] private void Test(); |
3.基础属性和组件的获取
3.1. 重要成员
成员 | 说明 | 示例 |
---|---|---|
gameObject | 获取脚本依附的 GameObject | print(gameObject.name); |
transform | 获取 GameObject 的位置信息 | print(transform.position); |
enabled | 获取或设置脚本激活状态 | this.enabled = false; |
3.2. 重要方法
方法 | 作用 | 参数 | 示例 |
---|---|---|---|
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)) { ... } |
4.GameObject游戏对象
4.1. 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); |
4.2. GameObject 静态方法
方法 | 作用 | 注意事项 | 示例 |
---|---|---|---|
CreatePrimitive | 创建带原始网格渲染器和碰撞体的游戏对象 | GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); | |
Find | 通过对象名查找单个激活对象 | 效率低,找不到返回 null ,无法找失活对象,多匹配时不确定找到哪个 | GameObject obj = GameObject.Find("对象名"); |
FindWithTag /FindGameObjectWithTag | 通过标签查找单个激活对象 | 找不到返回 null ,无法找失活对象 | GameObject obj = GameObject.FindWithTag("标签名"); |
FindGameObjectsWithTag | 通过标签查找多个激活对象 | 找不到返回空数组,无法找失活对象 | GameObject[] objs = GameObject.FindGameObjectsWithTag("标签名"); |
FindObjectOfType | 找到场景中挂载某脚本的对象 | 效率低,不仅遍历对象还遍历脚本,找不到返回 null | 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); |
4.3. 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); |
4.4. 次要成员方法(不建议使用,效率低)
方法 | 作用 | 示例 |
---|---|---|
SendMessage | 广播自己执行方法 | gameObject.SendMessage("方法名", 参数); |
BroadcastMessage | 广播自己和所有子对象执行方法 | gameObject.BroadcastMessage("方法名"); |
SendMessageUpwards | 广播自己和所有父对象执行方法 | gameObject.SendMessageUpwards("方法名"); |
5.Time时间
分类 | 变量 | 说明 | 受 timeScale 影响 | 使用场景 | 示例代码 |
---|---|---|---|---|---|
时间缩放比例 | timeScale | 控制时间流逝的标度,可用于慢动作、暂停等效果。默认值为 1 | - | 实现游戏的暂停、倍速等功能 | Time.timeScale = 0; // 时间停止 Time.timeScale = 2; // 2 倍速 |
普通帧间隔时间 (Update 内使用) | deltaTime | 完成上一帧所用的时间(秒) | 是 | 希望游戏暂停时物体停止移动的位移计算 | print("帧间隔时间: " + Time.deltaTime); transform.Translate(Vector3.forward * speed * Time.deltaTime); |
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); | |
物理帧间隔时间 (FixedUpdate 内使用) | fixedDeltaTime | 执行物理和其他固定帧率更新的时间间隔(秒) | 是 | 物理模拟相关的计算 | print("受 scale 影响的物理帧间隔时间: " + Time.fixedDeltaTime); |
fixedUnscaledDeltaTime | 从上一个固定帧到当前固定帧独立于 timeScale 的时间间隔(秒) | 否 | 不受时间缩放影响的物理模拟计算 | print("不受 scale 影响的物理帧间隔时间: " + Time.fixedUnscaledDeltaTime); | |
帧数 | frameCount | 从游戏开始到现在运行的总帧数 | 否 | 帧同步、帧率统计等 | print("从开始到现在游戏跑了 " + Time.frameCount + " 帧"); |
6.Transform
6.1. Transform 概述
Transform 主要用于游戏对象(GameObject)的位移、旋转、缩放、父子关系、坐标转换等相关操作。
6.2. Vector3 三维向量
分类 | 说明 | 示例 |
---|---|---|
申明方式 | 无参构造后赋值;传 xy 坐标参数的构造(默认 z 是 0);传 xyz 坐标参数的参数构造;结构体直接声明后赋值 | Vector3 v1 = new Vector3(); v1.x = 10; v1.y = 10; v1.z = 10; Vector3 v2 = new Vector3(10, 10); Vector3 v3 = new Vector3(10, 10, 10); Vector3 v4; v4.x = 10; v4.y = 10; v4.z = 10; |
基本计算 | 支持 +、 -、 *、 / 运算 | Vector3 v11 = new Vector3(1, 1, 1); Vector3 v12 = new Vector3(2, 2, 2); print(v11 + v12); // (3.0, 3.0, 3.0) |
常用向量 | 提供如 Vector3.zero 、Vector3.right 等常用向量 | print(Vector3.zero); // (0, 0, 0) |
距离计算 | Distance 方法返回向量之间的距离 | print(Vector3.Distance(v11, v12)); // 1.732051 |
6.3. 位置
变量 | 说明 | 注意事项 | 示例 |
---|---|---|---|
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; |
6.4. 朝向
可通过 transform.forward
、transform.up
、transform.right
得到对象当前的面朝向、头顶朝向、右手边朝向。
6.5. 位移
方式 | 说明 | 示例 |
---|---|---|
手动计算 | 路程 = 方向 * 速度 * 时间,一般放在 Update 里 | this.transform.position += this.transform.forward * 1 * Time.deltaTime; |
Translate 方法 | 根据 translation 的方向和距离移动变换,可指定相对坐标系 | this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.World); |
6.6. 角度和旋转
分类 | 变量/方法 | 说明 | 注意事项 | 示例 |
---|---|---|---|---|
角度 | 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); |
6.7. 缩放
变量 | 说明 | 注意事项 | 示例 |
---|---|---|---|
lossyScale | 相对世界坐标系的缩放大小(只读) | 只能获取,不能改变 | print(this.transform.lossyScale); |
localScale | 相对本地坐标系(父对象)的缩放大小 | 一般修改此变量,不能只改 xyz,用 Vector3 向量一起改 | print(this.transform.localScale); this.transform.localScale += Vector3.one * Time.deltaTime; |
6.8. 看向
LookAt
方法可让一个对象的面朝向某一个点或者某一个对象,一般写在 Update
内以持续更新。
示例 | 说明 |
---|---|
this.transform.LookAt(Vector3.zero); | 看向一个点,相对于世界坐标系 |
this.transform.LookAt(lookAtObj); | 看向一个对象,传入对象的 Transform 信息 |
6.9. 父子关系
操作 | 变量/方法 | 说明 | 示例 |
---|---|---|---|
获取父对象 | 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(GameObject.Find("Father2").transform); this.transform.SetParent(GameObject.Find("Father3").transform, 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); |
6.10. 坐标转换
转换类型 | 方法 | 说明 | 示例 |
---|---|---|---|
世界坐标转本地坐标 | 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)); |
7.Input 组件
7.1.鼠标输入(Update 中使用)
方法/属性 | 说明 | 参数/返回值 | 示例 | 注意事项 |
---|---|---|---|---|
mousePosition | 鼠标屏幕坐标(左下角为原点,z=0) | 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; | 滚轮滚动时触发,非持续 |
7.2.键盘输入(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) 开始游戏(); | 包括鼠标和键盘 |
7.3虚拟轴输入(控制移动/旋转)
方法 | 说明 | 返回值范围 | 默认轴 | 示例 | 适用场景 |
---|---|---|---|---|---|
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); | 镜头旋转 |
7.4触摸输入(移动设备)
方法/属性 | 说明 | 示例 | 注意事项 |
---|---|---|---|
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 ,禁用后仅识别第一个触摸点 |
7.5.手柄/虚拟按钮
方法 | 说明 | 参数 | 示例 | 配置 |
---|---|---|---|---|
GetButtonDown("Jump") | 手柄按钮按下瞬间(对应 Input Manager 中虚拟按钮) | string 按钮名(如 “Jump”) | if (Input.GetButtonDown("Jump")) 跳跃(); | 在 Edit > Project Settings > Input Manager 中配置 |
GetButton("Fire") | 手柄按钮长按 | string 按钮名 | if (Input.GetButton("Fire")) 持续射击(); | 支持键盘/手柄映射 |
7.6.重力感应(陀螺仪)
属性 | 说明 | 示例 | 注意事项 |
---|---|---|---|
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; | 手机旋转时的角速度 |
8.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 | 允许自动旋转为左横向,Home 键在左 | Screen.autorotateToLandscapeLeft = true; | - |
autorotateToLandscapeRight | 允许自动旋转为右横向,Home 键在右 | Screen.autorotateToLandscapeRight = true; | - | |
autorotateToPortrait | 允许自动旋转到纵向,Home 键在下 | Screen.autorotateToPortrait = true; | - | |
autorotateToPortraitUpsideDown | 允许自动旋转到纵向倒着看,Home 键在上 | Screen.autorotateToPortraitUpsideDown = true; | - | |
orientation | 指定屏幕显示方向 | Screen.orientation = ScreenOrientation.Landscape; | - | |
静态方法 | SetResolution | 设置分辨率(一般移动设备不使用) | Screen.SetResolution(1920, 1080, false); | - |
9.Camera摄像机
9.1Camera组件参数
分类 | 参数 | 说明 | 用途 | 示例或注意事项 |
---|---|---|---|---|
Clear Flags (清除标志) | Skybox(天空盒) | 确定将清除屏幕的哪些部分,此模式主要用于3D游戏,会渲染天空盒 | 3D游戏开发 | - |
`Solid Color(纯色) | 2D游戏适用,无需渲染天空盒,可在Background(背景)中修改颜色 | 2D游戏开发 | 在Background中选择合适颜色 | |
Depth only(仅深度) | 只画该层,背景透明,通常配合深度使用,用于多个摄像机叠加渲染的情况 | 多摄像机渲染 | 高深度摄像机常选此模式,配合选择要渲染的层级 | |
Don’t Clear(不清除) | 不移除原有内容,进行覆盖渲染,配合右键Game窗口tab选择编辑模式下不清除每一帧使用,一般较少使用 | 特殊渲染需求 | - | |
Background (背景) | - | 在绘制视图中的所有元素之后且没有天空盒的情况下,应用于剩余屏幕部分的颜色 | 设置背景颜色 | 选择合适的背景颜色 |
Culling Mask (剔除遮罩) | - | 可包含或忽略要由摄像机渲染的对象层,能选择性渲染部分层级,未选定的层级不会被当前摄像机渲染 | 控制渲染对象层级 | 在检视面板中将层分配到对象,指定只渲染对应层级的对象 |
Projection (投影) | Perspective(透视模式) | 切换摄像机模拟透视的功能,此模式有近大远小效果,常用于3D游戏制作 | 3D游戏开发 | - FOV Axis(Fov轴):决定光学仪器的视野范围,有Vertical(垂直)和Horizontal(水平)可选 - Field of view(视野):摄像机视角,范围在0 - 180度之间,一般默认60度 - Physical Camera(物理相机):勾选后可模拟真实世界中的摄像机 |
Orthographic(正交模式) | 没有近大远小效果,一般用于2D游戏制作 | 2D游戏开发 | Size(大小):视野轴,决定摄制范围 | |
Clipping Planes (裁剪平面) | - | 确定开始和停止渲染位置到摄像机的距离,对象位置需在近和远的区间内才能被渲染到 | 控制对象渲染范围 | 对象渲染异常或模型显示不全可能与此参数有关 |
Viewport Rect (Viewport矩形) | - | 通过四个值指示将在屏幕上绘制此摄像机视图的位置,在视口坐标中测量(值为0 - 1) | 多摄像机游戏 | XY设置渲染画面在Game窗口的起始位置,宽高设置渲染画面的比例,用于双摄像机或多摄像机游戏 |
Depth (深度) | - | 摄像机在绘制顺序中的位置,值越大的摄像机将绘制在值越小的摄像机之上 | 控制摄像机渲染顺序 | 低深度摄像机先渲染,高深度摄像机后渲染并可叠加覆盖 |
Rendering path (渲染路径) | - | 定义摄像机将使用的渲染方法的选项 | 选择渲染方式 | - |
Target Texture (目标纹理) | - | 引用将包含摄像机视图输出的渲染纹理,设置此引用将禁用此摄像机的渲染到屏幕功能 | 制作小地图等 | 在Project右键创建Render Texture渲染器纹理,拖拽到Target Texture上,可将摄像机画面渲染到纹理上 |
Occlusion Culling (遮挡剔除) | - | 为此摄像机启用遮挡剔除功能,即隐藏在其他对象后面的对象不会被渲染 | 优化渲染性能 | 默认勾选,可减少不必要的渲染 |
HDR | - | 为此摄像机启用高动态范围渲染 | 提升画面质量 | - |
MSAA | - | 为此摄像机启用多重采样抗锯齿 | 提升画面平滑度 | - |
Allow Dynamic Resolution (允许动态分辨率) | - | 为此摄像机启用动态分辨率渲染 | 优化性能 | - |
Target Display | - | 定义要渲染到的外部设备,值为1到8之间 | 多屏幕平台游戏开发 | - |
Target Eye | - | 用于VR游戏,选择渲染的眼睛(左或右) | VR游戏开发 | - |
9.2Camera参数和方法
9.2.1. 获取摄像机相关
静态成员 | 说明 | 示例代码 | 注意事项 |
---|---|---|---|
main | 获取主摄像机,即第一个启用且 tag 为 “MainCamera” 的摄像机(只读) | print(Camera.main); print(Camera.main.name); | 场景必须有 tag 为 “MainCamera” 的摄像机,否则报错;若有多个,获取的摄像机不确定 |
allCamerasCount | 获取当前场景中的摄像机数量 | print(Camera.allCamerasCount); | - |
allCameras | 得到场景中所有已启用的摄像机 | Camera[] allCameras = Camera.allCameras; print(allCameras.Length); | - |
9.2.2. 渲染相关委托
静态变量 | 说明 | 示例代码 |
---|---|---|
onPreCull | 任意摄像机开始剔除前触发的事件,可在剔除前做委托处理 | Camera.onPreCull += (c) => { /* 处理逻辑 */ }; |
onPreRender | 任意摄像机开始渲染前触发的事件 | Camera.onPreRender += (c) => { /* 处理逻辑 */ }; |
onPostRender | 任意摄像机完成渲染后触发的事件 | Camera.onPostRender += (c) => { /* 处理逻辑 */ }; |
9.2.3. 重要成员
成员 | 说明 | 示例代码 | 注意事项 |
---|---|---|---|
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,转换的世界坐标点是视口相交焦点;设置 Z 值后,是摄像机前方对应单位横截面上的世界坐标点 |
10.Light光面板
10.1光源组件
分类 | 参数 | 说明 | 示例或注意事项 |
---|---|---|---|
光源类型 | Directional (方向光) | 模拟远距离的光源,如太阳,光照方向一致 | - |
Spot (聚光灯) | 类似手电筒,有特定的发光范围和光锥角度 | 需设置 Range(范围)和 Spot Angle(光锥角度) | |
Point (点光源) | 类似小灯泡,向四周发光 | - | |
Area (面光源) | - | - | |
光源颜色和模式 | Color (光源颜色) | 设置光源的颜色 | - |
Mode (光源模式) | Realtime(实时光源):每帧实时计算,效果好但性能消耗大;Baked(烘焙光源):事先计算好,无法动态变化;Mixed(混合光源):预先计算 + 实时运算 | 根据性能和效果需求选择模式 | |
光源强度和间接系数 | Intensity (光源强度) | 控制光源的亮度 | - |
Indirect Multiplier (间接系数) | 改变间接光的强度,低于 1 每次反弹光更暗,大于 1 每次反弹光更亮 | - | |
阴影类型 | Shadow Type | NoShadows(关闭阴影);HardShadows(生硬阴影);SoftShadows(柔和阴影);Realtime Shadows(实时阴影) | 选择合适的阴影类型提升视觉效果 |
Strength (强度) | 阴影暗度,范围 0 - 1,越大越黑 | - | |
Resolution (分辨率) | 阴影贴图渲染分辨率,越高越逼真,消耗越高 | - | |
Bias (偏离) | 阴影推离光源的距离 | - | |
Normal Bias (法线偏离) | 阴影投射面沿法线收缩距离 | - | |
Near Panel (近平面) | 渲染阴影的近裁剪面 | - | |
剪影和效果 | Cookie (剪影) | 投影遮罩,一般用于聚光灯显示图案 | - |
Cookie Size (剪影大小) | 控制剪影的大小 | - | |
Draw Halo (绘制光晕) | 球形光环开关,可用于蜡烛等效果 | 要在 Game 窗口看到光晕需在摄像机上加 FlareLayer 脚本 | |
Flare(眩光) | 耀斑效果,类似太阳耀斑 | 要在 Game 窗口看到耀斑需在摄像机上加 FlareLayer 脚本 | |
渲染模式和剔除遮罩 | Render Mode | Auto(自动):运行时确定;Important(重要):以像素质量为单位进行渲染,效果逼真,消耗大;Not Important(非重要):以快速模式进行渲染 | 根据性能和效果需求选择渲染模式 |
Culling Mask (剔除遮罩) | 剔除遮罩层,决定哪些层的对象受到该光源影响 | - | |
代码控制 | intensity (光照强度) | 控制光的强度乘以光颜色 | light.intensity = 0.5f; |
10.2光面板(照明设置)
分类 | 参数 | 说明 | 示例或注意事项 |
---|---|---|---|
环境相关设置 | Skybox Material (天空盒材质) | 可以改变天空盒,可在 Project 窗口右键创建材质,材质选择成天空盒着色器 | - |
Sun Source (太阳来源) | 不设置会默认使用场景中最亮的方向光代表太阳 | - | |
环境光设置 | Source (环境光光源颜色) | Skybox(天空盒):天空和材质作为环境光颜色;Gradient(渐变):可以为天空、地平线、地面单独选择颜色和它们之间混合 | - |
Intensity Multiplier (环境光亮度) | 控制环境光的亮度 | - | |
Ambient Mode (环境模式) | 全局光照模式,只有启用了实时全局和全局烘焙时才有用,Realtime(实时,已弃用)、Baked(烘焙) | - | |
其它设置 | Fog (雾开关) | 控制雾的显示 | - |
Color (雾颜色) | 设置雾的颜色 | - | |
Mode (雾计算模式) | Linear(线性模式):随距离线性增加;Exponential(指数模式):随距离指数增加;Exponential Qquare(指数平方模式):随距离比指数更快的增加 | 不同模式下需设置不同的参数,如 Linear 模式需设置 Start 和 End 距离,指数模式需设置 Density 密度 | |
Halo Texture (光晕材质) | 光源周围挥着光环的纹理 | - | |
Halo Strength (光晕强度) | 光环可见性 | - | |
Flare Fade Speed (炫光交叉淡化速度) | 耀斑淡出时间,最初出现之后淡出的时间 | - | |
Flare Strength (炫光强度) | 耀斑可见性 | - | |
Spot Cookie (聚光灯剪影) | 聚光灯剪影纹理 | - |
11 物理系统 - 刚体
11.1.刚体组件参数
英文参数 | 说明 | 示例或注意事项 |
---|---|---|
Mass (质量) | 默认为千克,质量越大惯性越大 | - |
Drag (空气阻力) | 根据力移动对象时影响对象的空气阻力大小,0 表示没有空气阻力 | - |
Angular Drag (角阻力,扭矩阻力) | 通俗理解就是阻碍对象旋转的阻力,角阻力越大越不容易旋转。根据扭矩旋转对象时影响对象的空气阻力大小,0 表示没有空气阻力 | - |
Use Gravity (重力开关) | 是否受重力影响 | - |
Is Kinematic | 控制物理是否影响刚体。可以理解为开启后不受力的影响,只能通过 Transform 移动。如果启用此选项,则对象将不会被物理引擎驱动,只能通过 (Transform ) 对其进行操作。对于移动平台,或者如果要动画化附加了 HingeJoint 的刚体,此属性将非常有用 | - |
Interpolate (插值运算) | 让刚体物体移动更平滑 | 可以更改 FixTime ,改成一秒,这样对象会很突兀的一秒移动一次,这时开启插值运算就可以让刚体对象平滑移动 |
- None (无插值运算模式) | 不应用插值运算 | - |
- Interpolate (插值模式) | 插值将始终滞后一点,但比外推更流畅。根据前一帧的变换来平滑变换 | - |
- Extrapolate (外推模式) | 外推将根据当前速度预测刚体的位置。根据下一帧的估计变换来平滑变换 | - |
Collision Detection (碰撞检测模式) | 用于防止快速移动的对象穿过其它对象而不检测碰撞 | - |
- Discrete (离散检测) | 默认的碰撞检测模式。在每一帧中进行一次碰撞检测,适用于大多数普通物体。最省性能,但可能会错过高速物体的碰撞。适合一般速度移动的物体,不适合高速移动的小物体。对场景中的所有其他碰撞体使用离散碰撞检测。其他碰撞体在测试碰撞时会使用离散碰撞检测。用于正常碰撞(这是默认值) | - |
- Continuous (连续检测) | 提高了碰撞检测的精度,特别适合高速移动的物体。在每一帧中进行多次碰撞检测,避免高速物体穿过其他物体。比 Discrete 消耗更多的性能,但减少了穿透问题。适用于高速移动的物体,如子弹或快速飞行的物体。对动态碰撞体(具有刚体)使用离散碰撞检测,并对静态碰撞体(没有刚体)使用连续碰撞检测。设置为连续动态 (Continuous Dynamic ) 的刚体将在测试与该刚体的碰撞时使用连续碰撞检测。(此属性对物理性能有很大影响,如果没有快速对象的碰撞问题,请将其保留为 Discrete 设置)其他刚体将使用离散碰撞检测 | - |
- Continuous Dynamic (连续动态检测) | 针对快速移动的物体和其他静止或缓慢移动的物体之间的碰撞检测。结合 Continuous 和 Discrete 的优点,对高速物体进行多次检测,对慢速或静止物体进行一次检测。在保证精度的同时比 Continuous 更省性能。适用于快速移动的物体与静止或缓慢移动的物体之间的碰撞检测,如快速移动的角色或车辆。性能消耗高。对设置为连续 (Continuous ) 和连续动态 (Continuous Dynamic ) 碰撞的游戏对象使用连续碰撞检测。还将对静态碰撞体(没有刚体)使用连续碰撞检测。对于所有其他碰撞体,使用离散碰撞检测。用于快速移动的对象 | - |
- Continuous Speculative (连续推测检测) | 使用预测的方式进行碰撞检测。预测物体的未来位置,并在物体穿过其他物体前进行检测和处理。性能较高,精度也不错,但有时可能会出现误判。适合大多数需要高精度且有较高速度的物体。对刚体和碰撞体使用推测性连续碰撞检测。该方法通常比连续碰撞检测的成本更低 | - |
Constraints (刚体约束) | 对刚体运动的限制 | - |
- Freeze Position (冻结位置) | 有选择地停止刚体沿世界 X、Y 和 Z 轴的移动 | - |
- Freeze Rotation (冻结旋转) | 有选择地停止刚体围绕局部 X、Y 和 Z 轴旋转 | - |
Info (当前刚体的信息) | - | - |
11.2.刚体参数和方法
方法 | 详情 |
---|---|
获取刚体组件 | 使用this.GetComponent<Rigidbody>() 获取刚体组件,示例:rigidBody = this.GetComponent<Rigidbody>(); |
AddForce方法 | 相对世界坐标添加力,例如rigidBody.AddForce(Vector3.forward * 10); 。若要让对象相对于自身面朝向移动,可使用rigidBody.AddForce(this.transform.forward * 10); 。若想即使有阻力也让对象一直移动,可在Update 内持续调用此方法。 |
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(加速度模式):给物体增加持续加速度,忽略质量,如rigidBody.AddForce(Vector3.forward * 10, ForceMode.Acceleration); 。- Force(力模式):给物体添加持续力,与物体质量有关。 - Impulse(冲击力模式):给物体添加瞬间力,与物体质量有关,忽略时间。 - VelocityChange(瞬时速度模式):给物体添加瞬时速度,忽略质量和时间。 |
恒力场组件 | 搜索组件constant force 添加到物体上,修改其参数可实现不用代码添加力的效果,适用于保持某种力的场景。 |
刚体的休眠 | Unity为节约性能可能让刚体休眠。可使用IsSleeping 方法判断刚体是否休眠,如if (rigidBody.IsSleeping()) ;使用WakeUp 方法唤醒刚体,如rigidBody.WakeUp(); |
12. 物理系统 - 碰撞体
12.1.3D 碰撞器种类
- 盒状碰撞器 (
BoxCollider
) - 球状碰撞器 (
Sphere Collider
) - 胶囊碰撞器 (
Capsule Collider
) - 网格碰撞器 (
Mesh Collider
) - 轮胎碰撞器 (
Wheel Collider
) - 地形碰撞器 (
Terrain Collider
)
12.2.3D 碰撞器共同参数
英文参数 | 说明 | 示例或注意事项 |
---|---|---|
Edit Collider (编辑碰撞体) | 改变碰撞体大小 | - |
Is Trigger (是否是触发器) | 如果启用此属性,则该碰撞体将用于触发事件,并被物理引擎忽略。主要用于进行没有物理效果的碰撞检测 | - |
Material (物理材质) | 可以确定碰撞体和其它对象碰撞时的交互(表现)方式 | - |
Center (碰撞器中心) | 碰撞体在对象局部空间中的中心点位置 | - |
12.3.常用碰撞器
碰撞器类型 | 英文参数 | 说明 |
---|---|---|
BoxCollider (盒状碰撞器) | Size (大小) | 碰撞体在 X、Y、Z 方向上的大小 |
Sphere Collider (球状碰撞器) | Radius (半径) | 球形碰撞体的半径大小 |
Capsule Collider (胶囊碰撞器) | Radius (半径) | 胶囊体的半径 |
- | Height (高度) | 胶囊体的高度 |
- | Direction (轴向) | 胶囊体在对象局部空间中的轴向 |
异形物体使用多种碰撞器组合。刚体对象的子对象碰撞器信息参与碰撞检测。比如金字塔预设体,只在金字塔最高层级对象添加刚体,子对象的所有 Cube
都会参与碰撞检测。再比如一个 Cube
添加刚体,再给他添加两个空物体,两个空物体分别添加斜着的盒型碰撞器当做支架,这样这个 Cube
下落时就会被支架撑起来,即便两个空物体连模型都没有只有碰撞器。
12.4不常用碰撞器
碰撞器类型 | 英文参数 | 说明 | 示例或注意事项 |
---|---|---|---|
Mesh Collider (网格碰撞器) | 不常用的原因是性能消耗较高 | 默认不会显示绿色的碰撞器边框,开启 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 (选中此属性时,将启用树碰撞体) | - | - |
13. 物理系统 - 物理材质
英文参数 | 说明 |
---|---|
Dynamic Friction (动摩擦力) | 已在移动时使用的摩擦力。通常为 0 到 1 之间的值。值为零就像冰一样,值为 1 将使对象迅速静止(除非用很大的力或重力推动对象) |
Static Friction (静摩擦力) | 当对象静止在表面上时使用的摩擦力。通常为 0 到 1 之间的值。值为零就像冰一样,值为 1 将导致很难让对象移动 |
Bounciness (弹性) | 表面的弹性如何?值为 0 将不会反弹。值为 1 将在反弹时不产生任何能量损失,预计会有一些近似值,但可能只会给模拟增加少量能量 |
Friction Combine (摩擦力组合) | 两个碰撞对象的摩擦力的组合方式 |
- Average (平均值) | 对两个摩擦值求平均值 |
- Minimum (最小值) | 使用两个值中的最小值 |
- Maximum (最大值) | 使用两个值中的最大值 |
- Multiply (相乘) | 两个摩擦值相乘 |
Bounce Combine (反弹组合) | 两个碰撞对象的弹性的组合方式。其模式与 Friction Combine 模式相同 |
- Average (平均值) | 对两个摩擦值求平均值 |
- Minimum (最小值) | 使用两个值中的最小值 |
- Maximum (最大值) | 使用两个值中的最大值 |
- Multiply (相乘) | 两个摩擦值相乘 |
14. 碰撞检测函数
14.1碰撞器与触发器的核心条件对比
14.1.1.碰撞发生的必要条件
条件 | 说明 | 示例 |
---|---|---|
至少1个刚体(Rigidbody) | 提供物理模拟的动力源,负责受力与运动 | 下落的立方体(带刚体)碰撞地面(无刚体但有碰撞器) |
双方均有碰撞器(Collider) | 定义碰撞体积,缺一无法检测碰撞 | 子弹(刚体+碰撞器) vs 敌人(碰撞器) |
碰撞器未开启 Is Trigger | 必须为物理碰撞模式(默认关闭) | 关闭触发器的胶囊体碰撞 |
14.1.2.触发器触发的必要条件
条件 | 说明 | 示例 |
---|---|---|
至少1个碰撞器开启 Is Trigger | 标记为触发器,禁用物理碰撞效果 | 门的触发区域(碰撞器+Is Trigger) |
至少1个刚体(可选但推荐) | 非必须,但刚体存在时事件更稳定(静止物体需刚体才能触发) | 玩家(刚体)进入触发器区域(无刚体的碰撞器) |
双方碰撞器重叠 | 空间上产生交集(无需接触) | 球形触发器包裹玩家 |
14.2.物理碰撞检测响应函数
// OnCollisionEnter方法 碰撞触发接触时会自动执行这个函数
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 + "撞到了");
}
// OnCollisionExit方法 碰撞结束分离时会自动执行的函数
private void OnCollisionExit(Collision collision)
{
print(this.name + "被" + collision.gameObject.name + "结束碰撞了");
}
// OnCollisionStay方法 两个物体相互接触摩擦时会不停的调用该函数 接触但静止时不会调用
private void OnCollisionStay(Collision collision)
{
print(this.name + "一直在和" + collision.gameObject.name + "接触");
}
14.3触发器检测响应函数
// OnTriggerEnter方法 触发开始的函数 当第一次接触时会自动调用
protected virtual void OnTriggerEnter(Collider other)
{
print(this.name + "被" + other.gameObject.name + "触发了");
}
// OnTriggerExit方法 触发结束的函数 当水乳相融的状态结束时会调用一次
private void OnTriggerExit(Collider other)
{
print(this.name + "被" + other.gameObject.name + "结束水乳相融的状态了");
}
// OnTriggerStay方法 当两个对象水乳相融的时候会不停调用
private void OnTriggerStay(Collider other)
{
print(this.name + "和" + other.gameObject.name + "正在水乳相融");
}
15.Unity 音效系统
15.1.音频文件导入
分类 | 知识点 | 说明/示例 |
---|---|---|
支持格式 | WAV、MP3、OGG、AIFF | 推荐 WAV(无损)用于短音效,MP3/OGG(压缩)用于长音频 |
导入操作 | 直接拖拽音频到 Project 窗口 | - |
属性设置 | Force To Mono (强制单声道) | 多声道转单声道,适合语音类音频 |
LoadType (加载类型) | - Decompress On Load:小音效(内存高,加载快) - Compress in Memory:大音效(内存低,加载慢) - Streaming:极长音频(内存最小,CPU 高) | |
Preload Audio Data (预加载) | 勾选:进入场景预加载;不勾选:首次播放时加载 | |
预览与控制 | 底部工具栏播放/暂停/循环按钮 | 支持拖拽进度条预览音频 |
15.2.音频源(AudioSource)
15.2.1.音频源组件参数
分类 | 参数 | 说明 | 适用场景 | 注意事项 |
---|---|---|---|---|
基础设置 | AudioClip | 拖拽音频文件,指定播放内容 | 背景音乐、UI 音效、技能特效 | 未赋值时播放为空,需检查引用 |
Play On Awake | 启用时对象创建即播放(默认√) | 背景音乐(√)、UI 点击音效(×) | 动态生成的对象(如子弹)需关闭此选项 | |
Loop | 循环播放(默认×) | 背景音乐、环境音(如风声、水流) | 短音效(如按钮点击)禁用循环 | |
音量控制 | Volume | 音量(0-1,支持负数反向) | 主音量调节、角色音量衰减 | 结合 PlayerPrefs 存储用户设置 |
Priority | 优先级(0-255,0 最高,默认 128) | 多音效冲突时,高优先级优先播放(如警报音 > 脚步声) | 超过 32 个同时播放的音效可能爆音,需用 AudioMixer 管理 | |
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 | 输出到混音器(高级功能) | 多声道混音、分组控制(如 BGM/音效分离) | 需配合 AudioMixer 组件使用 |
15.2.2.音频源参数和方法
方法/属性 | 说明 | 示例代码 |
---|---|---|
Play() | 播放音频(从开头) | audioSource.Play(); |
PlayDelayed(5f) | 延迟播放(秒为单位) | audioSource.PlayDelayed(2f); // 2 秒后播放 |
Pause() /UnPause() | 暂停/恢复(保留播放位置) | audioSource.Pause(); |
Stop() | 停止并重置位置 | audioSource.Stop(); // 下次从开头播放 |
isPlaying | 检测是否播放(只读) | if (!audioSource.isPlaying) 播放完毕逻辑; |
多 AudioSource | 一个物体挂多个音频源,独立控制 | AudioSource[] audios = GetComponents<AudioSource>(); audios[1].Play(); |
15.3.麦克风录制
功能 | 方法/属性 | 示例代码 |
---|---|---|
获取设备 | Microphone.devices | string[] mics = Microphone.devices; // 打印所有麦克风名称 |
开始录制 | Microphone.Start(设备名, 循环, 时长, 采样率) | audioClip = Microphone.Start(null, false, 10, 44100); // 默认设备录 10 秒 |
停止录制 | Microphone.End(设备名) | Microphone.End(null); // 停止并保存录音 |
获取音频数据 | AudioClip.GetData(数组, 起始样本) | float[] data = new float[clip.channels * clip.samples];<br>clip.GetData(data, 0); |
播放录音 | 绑定 AudioSource 播放 | audioSource.clip = 录音Clip; audioSource.Play(); |
二、Unity基础
1.Mathf
1.1.常用基础方法(一般计算一次)
方法 | 说明 | 参数/返回值 | 示例代码 | 游戏场景 |
---|---|---|---|---|
Mathf.PI | 圆周率(3.14159265358979) | float (只读) | print(Mathf.PI); // 3.141593 | 圆周长、弧度计算 |
Mathf.Abs(float f) | 取绝对值 | f :数值返回 :绝对值 | Mathf.Abs(-5f); // 5 | 距离计算、伤害绝对值处理 |
Mathf.Clamp(float val, float min, float max) | 钳制数值(超出范围则取边界值) | val :原始值min/max :边界 | Mathf.Clamp(HP, 0, 100); // HP 不低于 0 不高于 100 | 血量、进度条限制 |
Mathf.Lerp(float a, float b, float t) | 线性插值(t 0→1 时从 a 平滑过渡到 b ) | a :起始值b :目标值t :插值系数 | pos = Mathf.Lerp(startPos, endPos, 0.5f); // 中间位置 | 平滑移动、渐变动画 |
Mathf.RoundToInt(float f) | 四舍五入取整 | f :浮点数返回 :整数 | Mathf.RoundToInt(3.6f); // 4 | 分数显示、帧数统计 |
Mathf.Sqrt(float f) | 平方根 | f :数值返回 :平方根 | Mathf.Sqrt(25f); // 5 | 距离计算(替代 Vector3.Distance ) |
Mathf.CeilToInt(float f) | 向上取整,返回大于或等于 f 的最小整数 | f :浮点数返回 :整数 | Mathf.CeilToInt(1.3f); // 2 | 资源计数,比如购买物品数量向上取整 |
Mathf.FloorToInt(float f) | 向下取整,返回小于或等于 f 的最大整数 | f :浮点数返回 :整数 | Mathf.FloorToInt(9.6f); // 9 | 资源计数,如计算可用资源的整数量 |
Mathf.Max(params float[] values) | 返回两个或更多值中的最大值 | values :可变长参数列表返回 :最大值 | Mathf.Max(1, 2, 3, 4, 5); // 5 | 比较多个角色的属性值,如攻击力最大值 |
Mathf.Min(params float[] values) | 返回两个或更多值中的最小值 | values :可变长参数列表返回 :最小值 | Mathf.Min(1, 2, 3, 4, 5); // 1 | 比较多个敌人的防御值,找出最小防御值的敌人 |
Mathf.Pow(float f, float p) | 返回 f 的 p 次幂 | f :底数p :指数返回 :幂值 | Mathf.Pow(2, 3); // 8 | 伤害计算,如技能伤害随等级的幂次增长 |
Mathf.IsPowerOfTwo(int value) | 判断一个数是否是 2 的 n 次方 | value :整数返回 :布尔值 | Mathf.IsPowerOfTwo(4); // true | 纹理尺寸判断,在图形处理中确保纹理尺寸为 2 的幂次方 |
Mathf.Sign(float f) | 返回 f 的符号,正数和 0 返回 1,负数返回 -1 | f :数值返回 :1 或 -1 | Mathf.Sign(-10); // -1 | 方向判断,如角色移动方向的正负判断 |
1.2.插值运算(Lerp)深度解析
用法 | 代码示例 | 效果 | 适用场景 |
---|---|---|---|
用法一:先快后慢 | pos = Mathf.Lerp(pos, target, Time.deltaTime * speed); | 初始速度快,逐渐趋近目标(类似阻尼效果) | 镜头跟随、物体平滑停止 |
用法二:匀速接近 | t += Time.deltaTime; pos = Mathf.Lerp(start, end, t); | t 累加,匀速到达目标(t≥1 时固定为 end ) | 倒计时、线性动画 |
扩展:颜色插值 | color = Color.Lerp(Color.red, Color.blue, t); | 平滑过渡颜色(t 0→1 时红→蓝) | UI 渐变、技能特效 |
1.3.三角函数与角度转换
方法/常量 | 说明 | 参数/返回值 | 示例代码 | 游戏场景 |
---|---|---|---|---|
Mathf.Rad2Deg | 弧度转角度常量(1 弧度 ≈ 57.29578°) | float (只读) | float deg = rad * Mathf.Rad2Deg; // 弧度转角度 | 欧拉角显示、UI 角度标注 |
Mathf.Deg2Rad | 角度转弧度常量(1° ≈ 0.01745329 弧度) | float (只读) | float rad = deg * Mathf.Deg2Rad; // 角度转弧度 | 三角函数计算、旋转方向 |
Mathf.Sin(float rad) | 正弦函数(输入弧度) | rad :弧度返回 :正弦值 | Mathf.Sin(90 * Mathf.Deg2Rad); // 1 | 正弦波运动(如摆锤、波浪效果) |
Mathf.Cos(float rad) | 余弦函数(输入弧度) | rad :弧度返回 :余弦值 | Mathf.Cos(0 * Mathf.Deg2Rad); // 1 | 方向向量计算(如敌人巡逻路径) |
Mathf.Atan2(float y, float x) | 反正切函数(返回弧度,计算 y/x 的角度) | y/x :坐标差值返回 :弧度 | float angle = Mathf.Atan2(y, x) * Mathf.Rad2Deg; // 目标角度 | 角色朝向、子弹追踪 |
2.坐标系
2.1.四大坐标系对比
坐标系 | 定义 | 原点 | 轴方向 | 典型场景 |
---|---|---|---|---|
世界坐标系 | 全局唯一,所有物体的绝对位置基准 | 场景中心(0,0,0) | X→右,Y→上,Z→前(默认) | 物体位置存储、碰撞检测 |
本地坐标系 | 相对于父对象的局部坐标系 | 父对象的位置 | 随父对象旋转/缩放而变化 | 子对象相对父对象的位置调整 |
屏幕坐标系 | 基于屏幕像素的2D坐标系 | 左下角(0,0) | X→右,Y→上,Z→深度(摄像机距离) | 鼠标位置获取、UI元素定位 |
视口坐标系 | 归一化的屏幕坐标系(0-1范围) | 左下角(0,0) | X→右,Y→上,Z→深度(0-1) | 分屏显示、全屏适配 |
2.2坐标转换核心方法
2.2.1. 世界 ↔ 本地(Transform 方法)
方向 | 方法 | 说明 | 参数/返回值 | 游戏场景 |
---|---|---|---|---|
世界→本地(点) | InverseTransformPoint(Vector3 worldPos) | 将世界点转为本地坐标(含位置+缩放+旋转) | worldPos :世界点返回 :本地点 | 子对象相对于父对象的位置计算 |
世界→本地(方向) | InverseTransformDirection(Vector3 worldDir) | 仅转换方向(忽略缩放,保留旋转) | worldDir :世界方向返回 :本地方向 | 子弹方向相对于坦克的朝向调整 |
本地→世界(点) | TransformPoint(Vector3 localPos) | 将本地点转为世界坐标(含父对象变换) | localPos :本地点返回 :世界点 | 炮塔位置转世界坐标生成子弹 |
本地→世界(方向) | TransformDirection(Vector3 localDir) | 仅转换方向(忽略缩放,保留旋转) | localDir :本地方向返回 :世界方向 | 角色朝向转世界方向(如技能释放方向) |
2.2.2. 世界 ↔ 屏幕(Camera 方法)
方向 | 方法 | 说明 | 关键参数 | 游戏场景 |
---|---|---|---|---|
世界→屏幕 | WorldToScreenPoint(Vector3 worldPos) | 世界点转屏幕坐标(Z为到摄像机的距离) | worldPos :世界点返回 :屏幕点(x,y,depth) | 头顶血条位置计算(UI锚点) |
屏幕→世界 | ScreenToWorldPoint(Vector3 screenPos) | 屏幕点转世界坐标(需设置Z轴,默认Z=0为近裁剪平面) | screenPos :屏幕点(需设Z)返回 :世界点 | 鼠标点击生成物体(需Z=10) |
2.2.3. 世界 ↔ 视口(Camera 方法)
方向 | 方法 | 说明 | 坐标范围 | 游戏场景 |
---|---|---|---|---|
世界→视口 | WorldToViewportPoint(Vector3 worldPos) | 世界点转视口坐标(X/Y∈[0,1],Z为深度) | worldPos :世界点返回 :视口点(0-1) | 检测物体是否在屏幕内(视口坐标>0且<1) |
视口→世界 | ViewportToWorldPoint(Vector3 viewportPos) | 视口点转世界坐标(X/Y∈[0,1],Z为深度) | viewportPos :视口点(需设Z,返回: 世界点 | 分屏游戏中,左半屏生成物体(X=0.5) |
3.Vector3
3.1基础属性(实例成员)
方法/属性 | 说明 | 参数/返回值 | 示例代码 | 游戏场景 | 注意事项 |
---|---|---|---|---|---|
magnitude | 向量的模长(只读) | float (返回长度) | Vector3 dir = target - transform.position;<br>float distance = dir.magnitude; | 敌人距离检测、射程判断 | 等价于 Mathf.Sqrt(x²+y²+z²) ,性能略低于Distance 方法 |
normalized | 单位向量(只读,方向不变,长度1) | Vector3 (返回单位向量) | Vector3 normDir = dir.normalized; | 方向移动(如角色朝向) | 若原向量为零向量,返回零向量(避免除以零) |
sqrMagnitude | 模长平方(只读,性能更高) | float (返回长度²) | if (dir.sqrMagnitude < 25) 触发攻击; | 快速距离比较(避免开平方) | 用于判断“是否在半径5内”时,比magnitude 快约50% |
3.2静态方法(基础运算)
方法 | 说明 | 参数/返回值 | 示例代码 | 游戏场景 | 几何意义 |
---|---|---|---|---|---|
Distance(a, b) | 两点间距离(等价于(b-a).magnitude ) | a,b:Vector3 返回:float | float dist = Vector3.Distance(A, B); | 子弹射程、寻路范围 | 欧几里得距离公式 |
Angle(from, to) | 两向量夹角(0°~180°,度数) | from,to:Vector3 返回:float | float angle = Vector3.Angle(forward, dir); | 扇形攻击范围、视野检测 | 基于点乘计算,忽略方向(仅角度) |
Cross(a, b) | 叉乘(左手坐标系,返回垂直于a、b的向量) | a,b:Vector3 返回:Vector3 | Vector3 up = Vector3.Cross(right, forward); | 判断左右方位(如敌人侧击) | 右手法则(数学)→ 左手法则(Unity) |
Dot(a, b) | 点乘(返回标量,a·b = | a | b | cosθ) | |
Lerp(a, b, t) | 线性插值(t∈[0,1],a到b的直线过渡) | a,b:Vector3 t:float 返回:Vector3 | pos = Vector3.Lerp(start, end, Time.deltaTime*3); | 平滑移动、镜头跟随 | t>1时固定为b,t<0时固定为a |
Slerp(a, b, t) | 球形插值(保持向量长度,球面过渡) | a,b:Vector3 t:float 返回:Vector3 | dir = Vector3.Slerp(forward, targetDir, 0.1f); | 平滑旋转、物体轨迹 | 常用于方向向量插值,避免“翻折” |
MoveTowards(current, target, maxDistanceDelta) | 向目标移动(自动限制步长) | current,target:Vector3 maxDistanceDelta:float 返回:Vector3 | transform.position = Vector3.MoveTowards(pos, target, speed*dt); | 角色寻路、敌人追击 | 等价于Lerp +Clamp ,更安全 |
4.Quaternion
4.1.构造与属性
方法/属性 | 类型 | 说明 | 参数/返回值 | 示例代码 | 游戏场景 | 注意事项 |
---|---|---|---|---|---|---|
Quaternion() | 构造函数 | 初始化四元数(默认单位四元数) | - | Quaternion q = new Quaternion(); | 空旋转初始化 | 等价于Quaternion.identity |
AngleAxis(angle, axis) | 静态 | 绕轴旋转(角度→四元数) | angle:float (度数)axis:Vector3 返回:Quaternion | Quaternion q = Quaternion.AngleAxis(90, Vector3.up); | 绕Y轴旋转90°(如门开合) | 轴向量无需归一化,内部自动处理 |
Euler(x, y, z) | 静态 | 欧拉角转四元数(按Z→X→Y顺序旋转) | x,y,z:float (度数)返回:Quaternion | Quaternion q = Quaternion.Euler(30, 0, 0); | 欧拉角转四元数(如角色转头) | 可能引发万向节死锁,避免直接修改欧拉角 |
eulerAngles | 实例属性 | 四元数转欧拉角(只读,自动处理-180~180°) | Vector3 (返回欧拉角) | Vector3 angles = q.eulerAngles; | 调试旋转角度 | 非连续旋转时可能跳跃(如从179°→-179°) |
identity | 静态属性 | 单位四元数(无旋转) | Quaternion (只读) | transform.rotation = Quaternion.identity; | 重置旋转(如复位操作) | 等价于new Quaternion(0,0,0,1) |
4.2.核心方法(旋转控制)
方法 | 类型 | 说明 | 参数/返回值 | 示例代码 | 游戏场景 | 对比/优化 |
---|---|---|---|---|---|---|
Lerp(a, b, t) | 静态 | 线性插值(非球面,可能翻转) | a,b:Quaternion t:float 返回:Quaternion | q = Quaternion.Lerp(rotA, rotB, 0.5f); | 快速插值(如UI旋转) | 比Slerp 快20%,但可能“翻折”(适合非方向敏感场景) |
Slerp(a, b, t) | 静态 | 球形插值(保持旋转方向,球面过渡) | a,b:Quaternion t:float 返回:Quaternion | transform.rotation = Quaternion.Slerp(rot, targetRot, dt*5); | 平滑转向(如角色转头) | 计算开销略高,适合方向敏感场景(如镜头旋转) |
LookRotation(dir, up) | 静态 | 看向目标方向(自动处理Up轴) | dir:Vector3 (目标方向)up:Vector3 (默认Vector3.up)返回:Quaternion | Quaternion look = Quaternion.LookRotation(target - pos); | 角色/镜头看向目标(如敌人) | 等价于Transform.LookAt ,但更灵活(可自定义Up轴) |
operator * (q1, q2) | 运算符 | 四元数乘法(q1先旋转,q2后旋转) | q1,q2:Quaternion 返回:Quaternion | transform.rotation *= Quaternion.AngleAxis(10, Vector3.up); | 绕自身轴连续旋转(如飞机翻滚) | 左乘:世界坐标系;右乘:本地坐标系(默认右乘) |
operator * (q, vec) | 运算符 | 向量绕四元数旋转 | q:Quaternion vec:Vector3 返回:Vector3 | Vector3 newDir = q * Vector3.forward; | 子弹方向计算(如扇形发射) | 等价于Transform.TransformDirection(vec) |
5.延迟函数
5.1.核心方法
方法 | 作用 | 参数 | 返回值 | 执行时机 | 典型场景 |
---|---|---|---|---|---|
Invoke(method, time) | 延时执行一次方法 | method : 函数名(字符串)time : 延迟时间(秒) | 无 | 第1次在time 秒后执行 | 倒计时提示、技能冷却结束触发 |
InvokeRepeating(method, time, repeat) | 延时重复执行方法 | method : 函数名time : 首次延迟repeat : 重复间隔(秒) | 无 | 第1次time 秒后,之后每repeat 秒执行 | 定时刷新(如敌人巡逻、自动射击) |
CancelInvoke([method]) | 取消延迟函数 | method : 可选(取消指定函数,不填则取消所有) | 无 | 立即生效 | 对象销毁前清理任务(如停止重复播放) |
IsInvoking([method]) | 判断是否存在待执行的延迟函数 | method : 可选(检查指定函数,不填则检查所有) | bool | 实时判断 | 避免重复开启延迟(如防止多次点击) |
5.2.对象状态对延迟函数的影响
对象状态 | Invoke/InvokeRepeating | CancelInvoke | 恢复执行 |
---|---|---|---|
激活(Active) | 正常执行 | 正常取消 | - |
失活(Inactive) | 继续执行(不受影响) | 正常取消 | 激活后继续(仅InvokeRepeating ) |
销毁(Destroy) | 立即终止 | 无效 | 无法恢复 |
脚本禁用(Disable) | 继续执行(脚本生命周期未结束) | 正常取消 | 启用后继续(仅InvokeRepeating ) |
5.3延迟函数 vs 协程(Coroutine)
对比项 | 延迟函数(Invoke) | 协程(Coroutine) |
---|---|---|
执行控制 | 简单(字符串函数名) | 灵活(可传参、中途中断) |
性能 | 较高(底层优化) | 中等(迭代器开销) |
参数支持 | 不支持(需代理) | 支持(通过IEnumerator 传参) |
生命周期依赖 | 独立于对象激活状态 | 依赖MonoBehaviour生命周期 |
适用场景 | 简单定时任务(如冷却、提示) | 复杂流程控制(如动画插值、异步加载) |
6.协同程序
6.1.协程方法
分类 | 方法 | 作用 | 执行机制 | 适用场景 | 核心特性 |
---|---|---|---|---|---|
启动 | StartCoroutine(ie) | 开启协程(迭代器函数) | 主线程分时执行,依赖yield 控制 | 异步加载、批量操作(如创建1000个物体) | 可传参,通过迭代器分步执行 |
关闭 | StopCoroutine(ie/c) | 停止指定协程(推荐用返回的Coroutine 对象) | 立即终止 | 中途取消(如加载失败) | StopAllCoroutines() 清空所有 |
暂停标记 | yield return X | - null /数字:下一帧- WaitForSeconds(t) :等待t 秒- WaitForFixedUpdate() :物理帧- WaitForEndOfFrame() :渲染后 | 调度器根据X 决定恢复时机 | 分步逻辑(如动画插值、截图) | 迭代器本质,代码块被拆分为多段执行 |
生命周期 | - | 组件失活继续执行,物体/组件销毁终止 | - | - | 依赖MonoBehaviour生命周期,适合Unity对象操作 |
本质 | 迭代器(C#语法糖) | 将函数逻辑拆分为可中断的“片段”,通过调度器恢复执行 | - | - | 非多线程,无并行,纯主线程分支 |
6.2.多线程与协程对比表
对比项 | 多线程(Thread) | 协程(Coroutine) |
---|---|---|
本质 | 操作系统层面的并行执行,独立于主线程 | 基于C#迭代器的分时执行,在主线程分支运行 |
访问Unity对象 | 不能直接访问Unity相关对象(如transform ) | 可正常访问Unity对象 |
性能开销 | 开销大,创建和销毁线程有资源消耗 | 开销小,基于迭代器实现 |
执行顺序 | 并行执行,执行顺序不确定 | 分时执行,可控制执行时机 |
适用场景 | 复杂逻辑计算(如A星寻路)、网络消息接收 | 异步加载(文件、场景)、批量创建对象 |
生命周期管理 | 需手动关闭,否则会持续运行 | 组件或物体销毁、物体失活时停止(组件失活除外) |
7.特殊文件夹
路径/文件夹 | 获取方式 | 创建要求 | 读写权限 | 打包后状态 | 典型用途 | 注意事项 |
---|---|---|---|---|---|---|
Application.dataPath | print(Application.dataPath) | 自动生成(无需创建) | 编辑模式:可读可写 发布后:只读 | 包含所有资源(只读) | 编辑模式调试路径(如加载外部配置) | 发布后不可写,避免运行时修改 |
Resources | 无(通过Resources.Load 访问) | 手动创建(Assets下) | 编辑/发布:只读 | 压缩加密(仅Resources.Load 可用) | 动态加载资源(如UI预制体、音效) | 打包后无法直接访问路径,避免存放过大资源 |
StreamingAssets | print(Application.streamingAssetsPath) | 手动创建(Assets下) | 编辑/PC:可读可写 移动:只读 | 不压缩(保留原始格式) | 存放需自定义加载的初始资源(如AB包、配置文件) | 移动平台(Android/iOS)仅可读,PC可读写 |
persistentDataPath | print(Application.persistentDataPath) | 自动生成(无需创建) | 全平台:可读可写 | 不打包(运行时生成) | 存储动态数据(如用户存档、下载资源) | 路径唯一,适合热更新和持久化存储(推荐使用) |
Plugins | 无(自动识别) | 手动创建(Assets下) | 编辑/发布:只读 | 包含插件(按需编译) | 存放平台专属插件(如iOS/Android SDK) | 不同平台文件需分目录(如Plugins/iOS /Android ) |
Editor | 无(仅编辑器可见) | 手动创建(Assets下) | 仅编辑器:可读可写 | 不打包(编辑器脚本专用) | 存放编辑器扩展脚本(如自定义面板) | 内容不会打入游戏包,编辑器模式下生效 |
Editor | 无(仅编辑器可见) | 手动创建(Assets下) | 仅编辑器:可读可写 | 不打包(编辑器脚本专用) | 存放编辑器扩展脚本(如自定义面板) | 内容不会打入游戏包,编辑器模式下生效 |
Standard Assets | 无(自动识别) | 手动创建(Assets下) | 编辑/发布:只读 | 包含资源(正常打包) | 存放Unity官方标准资源或项目基础资源,如角色控制器、物理组件等 | 避免滥用,按需提取资源;处理好编译顺序冲突;编辑器脚本放子级Editor文件夹 |
8.Resources
8.1.同步加载
方法 | 说明 | 参数/返回值 | 示例代码 | 适用场景 | 注意事项 |
---|---|---|---|---|---|
Resources.Load(path) | 同步加载资源(最常用) | path : 资源路径(无扩展名)返回 : Object | GameObject cube = Resources.Load<GameObject>("Prefabs/Cube"); | 小资源(UI、音效) | 阻塞主线程,大资源慎用 |
LoadAll(path) | 加载文件夹下所有资源(按类型过滤) | path : 文件夹路径返回 : Object[] | Object[] textures = Resources.LoadAll("Textures"); | 批量加载同目录资源 | 同名资源按类型区分,需强制转换 |
Load<T>(path) | 泛型加载(自动类型转换) | T : 目标类型返回 : T | AudioClip bgm = Resources.Load<AudioClip>("Music/BGM"); | 明确类型的资源(推荐) | 无需手动as ,代码更简洁 |
GameObject 加载 | 需配合Instantiate 实例化 | - | Instantiate(Resources.Load<GameObject>("Player")); | 预制体动态生成 | 直接加载GameObject 不实例化会占用内存,但无法卸载 |
8.2.异步加载
方法 | 说明 | 执行机制 | 示例代码 | 适用场景 | 核心优势 |
---|---|---|---|---|---|
LoadAsync<T>(path) | 异步加载(返回ResourceRequest ) | 新开线程加载,主线程检测完成 | ResourceRequest req = Resources.LoadAsync<Texture>("BigTex"); | 大资源(模型、高清纹理) | 避免主线程卡顿 |
回调监听 | req.completed += OnLoadEnd; | 加载完成触发回调 | void OnLoadEnd(AsyncOperation op) { tex = op.asset as Texture; } | 简单加载后逻辑 | 代码简洁,不支持多资源并行加载 |
协程加载 | yield return req; 或 while (!req.isDone) | 协程分时检测加载状态 | IEnumerator LoadCoroutine() { yield return req; 渲染纹理(); } | 复杂逻辑(如进度条、多资源) | 支持并行加载,灵活控制加载流程 |
进度跟踪 | req.progress (0~1,非精确) | 实时获取加载进度 | progressBar.value = req.progress; | 显示加载进度条 | 移动端可能因压缩导致进度跳跃 |
8.3.资源卸载
方法 | 说明 | 适用资源 | 示例代码 | 最佳实践 | 禁忌 |
---|---|---|---|---|---|
UnloadAsset(asset) | 卸载指定资源(非GameObject) | 纹理、音效、文本等非实例化资源 | Resources.UnloadAsset(tex); | 释放不再使用的单次加载资源 | 禁止卸载GameObject 预制体(会报错) |
UnloadUnusedAssets() | 卸载未使用的缓存资源(配合GC.Collect ) | 所有未引用的Resources资源 | Resources.UnloadUnusedAssets(); GC.Collect(); | 场景切换时清理内存 | 需在主线程调用,避免频繁调用 |
GameObject 卸载 | 实例化对象需Destroy() 释放 | 实例化的预制体 | Destroy(instance.gameObject); | 动态生成的对象(如子弹、UI) | 仅销毁实例,预制体缓存仍存在 |
9.SceneManager
9.1.场景同步加载
- 实现方式:使用
SceneManager.LoadScene
进行场景同步加载,需引用UnityEngine.SceneManagement
命名空间。
using UnityEngine.SceneManagement;
// 场景同步切换
SceneManager.LoadScene("Lesson21_场景异步加载Test");
- 缺点:切换场景时,Unity 会删除当前场景的所有对象,并加载下一个场景的相关信息。若当前场景或下一个场景的对象过多,该过程会非常耗时,导致玩家感受到卡顿。
9.2.场景异步加载
9.2.1 事件回调异步加载场景
- 原理:利用
SceneManager.LoadSceneAsync
方法在后台异步加载场景,通过AsyncOperation
类的completed
事件回调来处理加载完成后的逻辑。
// 封装的场景异步加载方法
private void LoadSceneAsyncWithCallback(string sceneName)
{
// 异步加载场景
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneName);
// 加载完成回调
asyncOperation.completed += (aO) =>
{
print("加载结束");
};
asyncOperation.completed += AsynLoadOver;
}
// 异步加载场景回调
private void AsynLoadOver(AsyncOperation ao)
{
print("AsynLoadOver");
}
- 注意事项:即使过场景时脚本或脚本依附的对象被销毁,异步加载的回调依然能够执行,因为回调被存储在事件中。
9.2.2 协程异步加载场景
- 原理:通过协程调用
SceneManager.LoadSceneAsync
进行异步加载,在加载过程中可以执行其他逻辑,如更新进度条。
// 异步加载场景协程函数
IEnumerator CoroutineAsynLoadScene(string name)
{
// 异步加载场景
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(name);
print("异步加载过程中打印的信息");
// 利用场景异步加载的进度更新进度条(不太准确)
while (!asyncOperation.isDone)
{
print(asyncOperation.progress);
yield return null;
}
// 等待异步加载结束
yield return asyncOperation;
print("异步加载结束后打印的信息");
// 也可根据游戏规则自定义进度条变化条件
}
}
9.3常用方法和属性
分类 | 属性/方法 | 描述 |
---|---|---|
属性 | activeScene | 获取或设置当前的活动场景,活动场景是当前正在运行的场景,一些操作会基于活动场景 |
属性 | sceneCount | 获取当前加载的场景数量,在管理多个同时加载的场景时有用 |
属性 | sceneCountInBuildSettings | 获取Build Settings中场景的总数,可了解项目中总共包含的场景数量 |
方法 | GetSceneAt(int index) | 根据索引获取已加载的场景,索引从0开始,范围是0到sceneCount - 1 |
方法 | GetSceneByName(string name) | 根据场景名称获取已加载的场景,若未找到则返回空的Scene 对象 |
方法 | GetSceneByPath(string path) | 根据场景的路径获取已加载的场景,路径是相对于项目的Assets文件夹的路径 |
方法 | UnloadSceneAsync(int sceneBuildIndex) | 异步卸载指定索引的场景,卸载场景会释放该场景占用的内存资源 |
方法 | UnloadSceneAsync(string sceneName) | 异步卸载指定名称的场景,卸载场景会释放该场景占用的内存资源 |
10.LineRenderer
10.1.LineRenderer组件参数
分类 | 参数 | 说明 | 常用值/操作 |
---|---|---|---|
场景点编辑 | Simplify Preview | 开启后线段预览更明显(简化密集点显示) | 勾选(调试用)/ 取消(正式) |
Tolerance | 点简化宽容度(值越大,线段越粗略,忽略密集点) | 1(默认,密集点时调大) | |
编辑点操作 | Subdivide Selected | 框选相邻点后插入新点(用于细化拐角) | 鼠标框选+点击(需启用编辑模式) |
添加点模式 | Input Mode | 点创建方式: - Mouse Position:摄像机位置创建(少用) - Physics Raycast:射线碰撞点创建(常用) | Physics Raycast(勾选) |
LayerMask | 射线检测层(仅响应指定层的点击,如地面、UI) | 勾选目标层(如“Ground”“UI”) | |
Min VertexDistance | 拖动创建点的最小间隔(避免过密) | 0.1~0.5米(根据手感调整) | |
通用属性 | Loop | 首尾点连接(闭合图形/开放线段) | true(攻击范围)/ false(轨迹线) |
PositionCount | 线段总点数(需先设置,再赋值) | 2(直线)~ 100(复杂曲线) | |
Use World Space | 坐标系模式: - true:世界坐标(固定) - false:本地坐标(随物体移动) | false(角色激光线) | |
渲染属性 | Start/End Width | 线段首尾宽度(支持曲线插值) | 0.01f(纤细)~ 0.5f(粗壮) |
Start/End Color | 线段渐变颜色(需材质支持) | Color.red → Color.blue(渐变) | |
Corner/End Vertices | 拐角/末端圆角精度(值越大越圆滑) | 2(默认)~ 5(高精度圆角) | |
Material | 线段材质(支持纹理/着色器,如火焰、激光) | 自定义材质(需关联主纹理) | |
光照相关 | Generate Lighting Data | 启用光照计算(材质需光源,如标准着色器) | true(有光照场景)/ false(无光照) |
Cast/Receive Shadows | 投射/接收阴影(增加场景真实感) | 按需勾选(默认关闭以优化性能) | |
高级设置 | Alignment | 线段对齐方式: - View:始终朝向相机 - Transform Z:沿物体Z轴方向 | View(UI指引线)/ Transform Z(模型轮廓) |
Texture Mode | 纹理映射模式: - Stretch:单次拉伸 - Tile:平铺重复 | Stretch(激光纹理)/ Tile(铁链纹理) | |
性能优化 | Dynamic Occludee | 动态遮挡剔除(减少不可见线段渲染) | 勾选(复杂场景) |
排序控制 | Sorting Layer | 渲染层级(避免被UI遮挡) | 自定义层级(如“Foreground”) |
10.2.LineRenderer参数和方法
功能 | API | 说明 | 注意事项 |
---|---|---|---|
动态创建线段 | AddComponent<LineRenderer>() | 给 GameObject 添加 LineRenderer 组件 | 需先创建空物体 |
设置闭合状态 | lineRenderer.loop = true; | 闭合线段(首尾相连) | 需配合 PositionCount ≥ 2 |
设定宽度 | lineRenderer.startWidth = 0.02f; lineRenderer.endWidth = 0.02f; | 设置线起点和终点处的宽度,支持动态修改 | 实时刷新需在 Update 中调用 |
设定颜色 | lineRenderer.startColor = Color.white; lineRenderer.endColor = Color.red; | 设置线起点和终点处的颜色,支持动态修改 | 实时刷新需在 Update 中调用 |
设置材质 | material = Resources.Load<Material>("火焰材质"); lineRenderer.material = material; | 赋值自定义材质,支持纹理动画 | 材质需包含主纹理(Main Tex) |
设置点个数 | lineRenderer.positionCount = 4; | 设置或获取顶点数 | 设置点时,要先设置点的个数 |
批量设置点 | lineRenderer.SetPositions(new Vector3[] { new Vector3(0,0,0),new Vector3(0,0,5), new Vector3(5,0,5)}); | 一次性设置所有点 | 需先定义 PositionCount ,数组长度需 ≤ PositionCount |
单点修改 | lineRenderer.SetPosition(3, new Vector3(5, 0, 0)); | 单独修改某点坐标 | index 从 0 开始,坐标基于 useWorldSpace 的设置 |
坐标系切换 | lineRenderer.useWorldSpace = false; | 切换为本地坐标系(线段随物体移动) | 动态切换需谨慎,可能导致坐标混乱 |
设置光照影响 | lineRenderer.generateLightingData = true; | 配置线以生成法线和切线,让场景光照影响线 | 若材质需要光照效果,需开启此选项 |
11.物理系统-范围检测
11.1.范围检测基础
分类 | 要点 | 关键细节 |
---|---|---|
定义 | 瞬时检测指定范围内的对象(无实体碰撞器,仅计算) | 用于攻击范围、触发判定等瞬时逻辑 |
必备条件 | - 对象需含碰撞器(Collider) - 检测代码执行时触发(非持续检测) | 无刚体也可检测(区别于碰撞事件) |
层级过滤 | LayerMask 位运算(左移+或运算) | 1 << LayerMask.NameToLayer("Enemy") 表示仅检测Enemy层 |
触发器处理 | QueryTriggerInteraction 枚举:- UseGlobal (全局设置)- Collide (检测触发器)- Ignore (忽略触发器) | 全局设置路径:Edit > Project Settings > Physics > Queries Hit Triggers |
11.2.核心方法
API | 形状 | 参数 | 返回值 | 典型场景 | 优化建议 |
---|---|---|---|---|---|
OverlapBox | 盒状 | 中心坐标, 半尺寸, 旋转, 层掩码, 触发器模式 | Collider[] (动态数组) | 矩形攻击范围(如地刺、AOE) | 避免高频调用(每次生成新数组) |
OverlapBoxNonAlloc | 盒状 | 中心坐标, 半尺寸, 预分配数组, 层掩码, 触发器模式 | int (碰撞数) | 高频检测(如每帧扫描) | 预分配数组(colliders = new Collider[10] )减少GCAlloc |
OverlapSphere | 球形 | 中心坐标, 半径, 层掩码, 触发器模式 | Collider[] (动态数组) | 圆形范围(如角色拾取、技能半径) | 配合LayerMask 过滤非目标层 |
OverlapSphereNonAlloc | 球形 | 中心坐标, 半径, 预分配数组, 层掩码, 触发器模式 | int (碰撞数) | 性能敏感场景(如子弹爆炸检测) | 提前计算半径(避免重复计算) |
OverlapCapsule | 胶囊状 | 端点1, 端点2, 半径, 层掩码, 触发器模式 | Collider[] (动态数组) | 柱状范围(如角色近战攻击、NPC视野) | 用Vector3.ProjectOnPlane 计算地面投影 |
OverlapCapsuleNonAlloc | 胶囊状 | 端点1, 端点2, 半径, 预分配数组, 层掩码, 触发器模式 | int (碰撞数) | 复杂地形检测(如爬墙判定) | 缓存端点坐标(减少重复赋值) |
12.射线检测
分类 | 核心内容 | 关键细节 |
---|---|---|
基础概念 | 瞬时发射射线,检测与碰撞器的交点(无实体,仅计算) | 适用:鼠标选择、射线攻击、视线阻挡判定 条件:目标需有碰撞器(无需刚体) |
Ray 类 | - 构造:new Ray(origin, direction) - 摄像机射线: Camera.ScreenPointToRay(鼠标位置) | origin :射线起点direction :方向向量(非终点)屏幕点转射线用于UI/场景交互 |
核心API | Physics.Raycast (单碰撞)参数: (射线/起点, 方向, out 碰撞信息, 距离, 层掩码, 触发器模式) | 返回:bool 用途:检测首个碰撞目标(如射击命中) 层掩码: 1 << 层号 (如1 << 8 ) |
Physics.RaycastAll (多碰撞)参数: (射线/起点, 方向, 距离, 层掩码, 触发器模式) | 返回:RaycastHit[] (无序数组)用途:获取所有碰撞目标(如区域内敌人) | |
Physics.RaycastNonAlloc (预分配)参数: (射线/起点, 方向, 预分配数组, 距离, 层掩码, 触发器模式) | 返回:int (碰撞数)优化:避免GCAlloc,适合高频检测(如每帧扫描) | |
RaycastHit | - collider :碰撞器- point :交点坐标- normal :碰撞面法线- distance :起点到交点距离 | normal 用于特效朝向(如弹孔法线对齐)point 用于生成命中特效(如子弹痕迹) |
参数顺序 | 必记顺序: 1. 射线/起点 2. 方向(非必填,重载支持) 3. out 碰撞信息 (单碰撞)4. 距离(0=无限) 5. 层掩码 6. 触发器模式 | 易错:层掩码误填为第2参数(正确:第4/5位) 示例: Raycast(ray, out hit, 100, 1<<8) |
触发器处理 | QueryTriggerInteraction 枚举:- Collide (检测触发器)- Ignore (忽略)- UseGlobal (全局设置) | 全局设置路径:Project Settings > Physics > Queries Hit Triggers (默认检测触发器) |
性能优化 | - 预分配数组:RaycastHit[] hits = new RaycastHit[10] - 缓存射线:避免重复创建(如 Camera.main 缓存) | NonAlloc 比RaycastAll 少生成临时数组,适合高频场景(如技能检测) |
典型场景 | 1. 鼠标选物体:ScreenPointToRay + Raycast (层过滤UI)2. 射线攻击:检测首个碰撞目标( distance 限制射程)3. 视线阻挡: Raycast 返回distance 与预设值比较 | 示例:FPS射击检测墙体遮挡:if (hit.distance < 敌人距离) 被遮挡 |
三、Unity核心
1.图片纹理
1.1.Unity支持的图片格式
BMP
:是Windows操作系统的标准图像文件格式,特点是几乎不进行压缩,占磁盘空间大。
TIF
:基本不损失图片信息的图片格式,缺点是体积大。
JPG
:一般指JPEG格式,属于有损压缩格式,能够让图像压缩在很小的存储空间,一定程度上会损失图片数据,无透明通道。
PNG
:无损压缩算法的位图格式,压缩比高,生成文件小,有透明通道。
TGA
:支持压缩,使用不失真的压缩算法,还支持编码压缩。体积小,效果清晰,兼备BMP的图像质量和JPG的体积优势,有透明通道。
PSD
:是PhotoShop(PS)图形处理软件专用的格式,通过一些第三方工具或自制工具可以直接将PSD界面转为UI界面。
此外,Unity还支持EXR、GIF、HDR、IFF、PICT等格式。其中,在Unity中最常用的图片格式是JPG、PNG和TGA三种。
1.2.纹理类型参数
纹理类型 | 描述 | 相关参数及解释 |
---|---|---|
Default(默认) | 大部分导入的模型贴图都是该类型 | 无特殊参数 |
sRGB(Color Texture)(sRGB颜色纹理) | 启用可以将纹理存储在伽马空间中(对每一个像素做一次幂函数运算),一般勾选。 人眼看线性渐变的图片会感觉不是线性的,要用伽马控件校正,校正后的图片人眼看是线性渐变的 | sRGB(Color Texture):一般勾选,用于伽马校正 |
Alpha Source(Alpha源) | 指定如何生成纹理的Alpha通道 | - None:无论输入纹理是否有Alpha通道,导入的纹理都没有Alpha通道 - Input Texture Alpha:使用输入纹理中的Alpha通道 - From Gray Scale:从输入纹理RGB值的平均值生成Alpha,一般不用 |
Alpha Is Transparency(Alpha是透明的) | 启用可以避免边缘上的过滤瑕疵 | 一般启用 |
Normal map(法线贴图) | 法线贴图格式:在原物体的凹凸表面的每个点上均作法线(法线是垂直于某个点的切线的方向向量)。 游戏中有时不使用高精度、多三角面片的模型(避免卡顿),记录高精度模型的各个点的法线做成法线贴图,在低精度模型中,通过法线贴图和一些着色器算法,在三角面片更少的低精度模型里能得到效果更好、看起来更高精度的效果 | - Create From Grayscale:启用此属性可以从灰度高度贴图创建法线贴图 - Bumpiness:控制凹凸程度,值越大凹凸感越强 - Filtering: - Sharp:生成比标准模式更锐利的法线贴图 - Smooth:使用标准算法生成法线贴图 |
Editor GUI and Legacy GUI(编辑器GUI和旧功能GUI) | 一般在编辑器中或者GUI上使用的纹理 | 无特殊参数 |
Sprite(2D and UI)(精灵(2D和UI)) | 2D游戏或者UGUI中使用的格式 | - Sprite Mode: - Single:按原样使用精灵图像,图片是一张图(非图集)就选这个选项 - Multiple:瓦片模式,如果是图集,使用该选项,可以在Sprite Editor编辑窗口自定义图片 - Polygon:网格精灵模式,如果图片或者图集是多边形可以选择这种模式 - Pixels Per Unit:世界空间中的一个距离单位(Unity中为一米)对应多少像素 - MeshType(只有Sprite模式是Single模式和Multiple模式才支持,因为Polygon模式可自定义多边形大小): - Full Rect:创建四边形,将精灵显示在四边形上,若图片为三角形,渲染到3D引擎里会创建矩形做成两个三角面片来渲染 - Tight:基于像素Alpha值来生成网格,更加贴合精灵图片的形状,任何小于32*32的精灵都使用FullRect模式,即使设置成Tight模式也是,若图片为三角形,渲染到3D引擎里会把三角形切割成几个三角面片来渲染 - Extrude Edges:使用滑动条确定生成的网格中精灵周围留出的区域大小,可理解为三角形图片边的溢出渲染区域的大小 - Pivot(Single模式才有此选项):精灵图片的轴心点,对应九宫格布局的九个点,还可以自定义 - Generate Physics Shape(只有Single 和Multiple模式才可使用,因为Polygon是自己手动设置的):启用此选项,Unity会自动根据精灵轮廓生成默认物理形状,若图片要进行物理判断(如碰撞器或者物理检测),就勾选它 - Sprite Editor:编辑Sprite,需要安装2D Sprite包 |
Cursor(光标) | 自定义光标,设置鼠标的图片 | 无特殊参数 |
Cookie(光源剪影格式) | 用于设置光照类型的纹理形状 | - Light Type: - Spotlight:聚光灯类型,需要边缘纯黑色纹理,TextureShape纹理形状需设置为2D形状 - Directional:方向光,平铺纹理,需要设置TextureShape纹理形状为2D形状 - Point:点光源,需要设置TextureShape纹理形状为立方体形状 |
Lightmap(光照贴图) | 光照贴图格式 | - Single Channel:纹理只需要单通道的格式 - Channel: - Alpha:使用Alpha通道,不允许进行压缩 - Red:使用红色通道 |
1.3.纹理形状参数
Texture Shape(纹理形状) | 描述 |
---|---|
2D | 最常用设置,这些纹理将应用于模型和 GUI 元素上 |
Cube(立方体) | 主要用于天空盒和反射探针 |
Mapping(贴图) | 如何将纹理投影到游戏对象上,具体如下: - Auto(自动):根据纹理信息创建布局。 - 6 Frames Layout(6 帧布局(立方体环境)):纹理包含以标准立方体贴图布局之一排列的六个图像。 - Latitude-Longitude Layout(纬度精度布局(立方体)):将纹理映射到 2D 维度/经度。 - Mirrored Ball(镜面球):将纹理映射到类似球体的立方体贴图上。 |
Convolution Type(卷积型) | 纹理的过滤类型,具体如下: - None(无):无过滤。 - Specular(镜面(光泽反射)):将立方体作为反射探针。 - Diffuse(漫反射(发光)):将纹理进行过滤表示辐照度,可作为光照探针。 |
Fixup Edge Seams(固定边缘对接处) | 适用情况:当 Convolution Type 为 None 和 Diffuse 时才有用。 作用:解决低端设备上立方体贴图过滤错误的问题。 |
1.4.纹理高级参数设置
参数 | 描述 | 选项及说明 |
---|---|---|
Non - Power of 2(非2次幂) | 处理纹理尺寸非2的幂的情况。因图形学规则,纹理通常须是2的幂尺寸 |
|
Read/Write Enabled(读/写已开启) | 启用后可使用Unity方法从纹理获取数据 | 一般在需要代码获取图片数据时开启,否则会占内存 |
Streaming Mipmaps(流式Mipmaps) | 启用后可使用纹理串流 | 用于控制加载在内存中的Mipmap级别,减少Unity对纹理所需内存总量,用性能换内存 |
Mip Map Priority(Mipmap优先级) | - | Unity根据该优先级确定分配资源时优先考虑的Mipmap |
Generate Mip Maps(生成MipMaps贴图) | 允许生成MipMap | 开启后可在下方图片栏滚动条调整MipMaps尺寸,2D游戏一般不启用,3D游戏视情况而定 |
Border Mip Maps(边框Mip贴图) | - | 启用可避免颜色向外渗透到较低MIP级别的边缘 |
Mip Map Filtering(Mip贴图过滤) | 优化图像质量的过滤方法 |
|
Mip Maps Preserve Coverage(MipMaps保留覆盖范围) | - | Mipmap的Alpha通道在Alpha测试期间保留覆盖率 |
Alpha Cutoff Value(Alpha修剪值) | - | 覆盖率参考值 |
Fadeout Mip Maps(交叉淡化Mip贴图) | - | 级别递减时使Mipmap淡化为灰色 |
1.5.纹理平铺拉伸参数
参数 | 描述 | 选项及说明 |
---|---|---|
Wrap Mode(贴图间拼接模式) | 平铺纹理时的方式。可通过创建四边形面片、材质,拖拽图片,修改平铺拉伸参数和材质的平铺 XY 及偏移来查看效果 |
|
Filter Mode(过滤模式) | 纹理在通过 3D 变化拉伸时的过渡方式 |
|
Aniso Level | 以大角度查看纹理时提高纹理质量,但性能消耗高 | - |
1.6.纹理平台打包相关参数
参数 | 描述 | 选项及说明 |
---|---|---|
Max Size(最大尺寸) | 设置导入纹理的最大尺寸,可将美术提供的大尺寸图片限制在一定范围内,一般选择 2048 | - |
Resize Algorithm(重设大小算法) | 当纹理尺寸大于指定的 Max Size 时,用于缩小纹理的算法 | Mitchell:默认米切尔算法,是常用的尺寸缩小算法 Bilinear:使用双线性插值调整大小,对于细节重要的图片,比米切尔算法保留更多细节 |
Format(格式) | 纹理格式,各平台支持的格式不同,若选择 Automatic,会根据平台使用默认设置 | 都支持的格式 移动端和网页端特有格式 iOS:选择默认的纹理压缩设置 (PVRTC) 可获得更大兼容性;若应用程序不包含 OpenGL ES 2 支持,可选择 ASTC 格式,该格式质量更好、灵活性更高且压缩速度比 PVRTC 快 Android:因安卓设备众多且标准不一,一般会根据不同设备标准制作多个安装包。 - 构建以 OpenGL ES 3 为目标的 APK:访问 Android 的 Player Settings(菜单:Edit > Project Settings >Player Settings,然后选择 Android 类别),向下滚动到 Graphics APIs 部分,确保 OpenGL ES 2 不在列表中,然后构建 APK(菜单:File > Build Settings,然后单击 Build) - 构建以 OpenGL ES 2 为目标的单独 APK:访问 Android Player Settings,向下滚动到 Graphics APIs 部分,在列表中添加 OpenGL ES 2 并删除 OpenGL ES 3 和 Vulkan,然后构建 APK |
Compression(压缩) | 选择纹理的压缩类型,帮助 Unity 正确选择压缩格式,会根据平台和压缩格式的可用性进行压缩 | None(无):不压缩纹理 Low Quality(低质量):以低质量格式压缩纹理 Normal Quality(法线质量):以标准格式压缩纹理 High Quality(高质量):以高质量格式压缩纹理,一般选择高质量 |
Use Crunch Compression(使用 Crunch 压缩) | 启用后,使用 Crunch 压缩,Crunch 是一种基于 DXT 或 ETC 纹理压缩的有损压缩格式,特点是压缩时间长,解压速度快 | - |
Split Alpha Channel(拆分 Alpha 通道) | Alpha 通道分离,可节约内存,会把一张图分成两张纹理,一张包含 RGB 数据,一张包含 Alpha 数据,渲染时再合并渲染 | - |
Override ETC2 fallback(覆盖 ETC2 回退) | 在不支持 ETC2 压缩的设备上使用的格式 | - |
2.SpriteEditor精灵编辑器
2.1.Single 图片编辑功能
功能 | 描述 |
---|---|
Sprite Editor 基础图片设置 | Name:设置图片名称。 Position:调整图片在其中的偏移位置以及宽高。 Border:设定九宫格的 4 条边。 Pivot:确定轴心(中心)点的位置。 Pivot Unit Mode: Normalized:标准化模式,取值在 0 至 1 之间。 Pixels:像素模式,显示当前轴心在图片中的像素位置。 Custom Pivot:自定义轴心点。 |
Custom Outline 自定义边缘线(决定渲染区域) | 可自定义精灵网格的轮廓形状。默认在矩形网格上渲染,边缘外部透明区域会被渲染,存在性能浪费。通过自定义轮廓,可缩小透明区域,提升性能。 Snap 捕捉:使控制点贴近最近的像素,默认选择该选项。 Outline Tolerance:控制轮廓点的复杂性和准确性,取值范围 0 至 1,值越大,轮廓点越多,越准确。 Generate:生成网格轮廓,可手动编辑点,修改后需应用。 |
Custom Physics Shape 自定义物理形状(决定碰撞判断区域) | 用于自定义精灵图片的物理形状,主要针对需要物理碰撞判断的 2D 图形,确定碰撞检测区域,其参数和操作与自定义边缘线基本相同。 |
Skinning Editor 皮肤编辑器 | 暂不讲解,后续涉及。 |
Secondary Textures 辅助纹理(为图片添加特殊效果) | 可将其他纹理与该精灵图片关联。点击加号添加关联图片作为辅助纹理并命名,着色器可利用这些辅助纹理进行效果处理,赋予精灵其他效果。 |
2.2.Multiple 图集元素分割
当图片资源为图集时,需将模式设为 Multiple,借助 Sprite Editor 进行图集元素分割:
操作 | 描述 |
---|---|
切片操作 | 在 Sprite Editor 窗口中,选中要删除的切片按 Delete 键删除;也可按住鼠标左键用选择框进行切片。若 Delete 键无法删除,可将框移至空白处,点击 Trim 剪裁来删除。 |
切片设置 | 选中切片可设置其信息,与 Single 模式下图片编辑类似,设置好后可抠出切片图使用。编辑参数后选择切片进行切割,若切割不准确可手动调整,切割后可通过下拉按钮查看切割后的图,可用于制作动画帧图。 |
分割参数讲解 | Slice Type 切片类型: Automatic 自动分割: Pivot 轴心:设置单张图片轴心点位置。 Custom Pivot 自定义轴心点:自定义轴心点。 Method 方法: Delete Existing 删除现有:替换已选的任何矩形。 Smart 聪明:尝试创建新矩形并保留或调整现有矩形。 Safe 安全:添加新矩形而不改变已存在的矩形。 Grid By Cell Size 按单元格大小分割:仅适用于规范矩形图集。 Pixel Size 像素大小:设置单元格宽高。 Offset 偏移:设置左上角偏移位置。 Padding 填充:设置与边缘的偏移位置以及矩形间的偏移缝隙。 Keep Empty Rects:决定是否保留空矩形,一般不勾选。 Grid By Cell Count 按单元格数量分割:设置 Column & Row(行列数)。 Trim 剪裁:选中切片单元格,可自动去除单元格上多余的透明部分。 |
2.3.Polygon 多边形编辑
若使用的资源是多边形资源,可将模式设为 Polygon,在 Sprite Editor 中进行快捷设置,但实际开发中较少使用:
操作 | 描述 |
---|---|
多边形编辑参数 | 点击更改形状,可设置边数,范围在 3 至 128 之间。自定义边缘线会自动生成渲染范围,仅显示圈定的图形。需注意,设置为 Polygon 多边形后再改回 Single 模式,需重新选择自定义边缘线生成,否则会保留上次的边缘线。 |
3.Animator
3.1.Animator 动画器组件参数说明
参数 | 描述 | 选项及说明 |
---|---|---|
Controller(控制器) | 对应的动画控制器(状态机) | - |
Avatar(替身) | 对应的替身配置信息(在讲解 3D 模型时详细讲解) | - |
Apply Root Motion(应用根运动) | 是否启用动画位移更新 | 若启用,动画中的位移信息会更新物体的位置;若不启用,物体位置不受动画位移影响 |
UpdateMode(更新模式) | 一般不修改该参数 |
|
Culling Mode(裁剪剔除模式) | - |
|
3.2.Animator 动画器代码控制
获取 Animator 组件
//我们用代码控制状态机切换主要使用的就是Animator提供给我们的API
//我们知道一共有四种切换条件 int float bool trigger
//所以对应的API也是和这四种类型有关系的
Animator animator = this.GetComponent<Animator>();
Animator.SetXXX 方法:通过状态机条件切换动画
//通过状态机条件切换动画
//设置动画参数状态
// 设置浮点数类型的动画参数
animator.SetFloat("条件名", 1.2f);
// 设置整数类型的动画参数
animator.SetInteger("条件名", 5);
// 设置布尔类型的动画参数
animator.SetBool("条件名", true);
// 设置触发类型的动画参数
animator.SetTrigger("条件名");
Animator.GetXXX 方法:获得动画参数状态
//获得动画参数状态
// 获取浮点数类型的动画参数值
animator.GetFloat("条件名");
// 获取整数类型的动画参数值
animator.GetInteger("条件名");
// 获取布尔类型的动画参数值
animator.GetBool("条件名");
// 直接切换动画(除非特殊情况,不然一般不使用)
// 注意:状态名和动画名不一样,动画名拖进来默认名字就是状态名,但是可以修改得和动画名不一样
animator.Play("状态名");
3.3 Animator 窗口中动画状态设置相关参数
参数 | 描述 | 选项及说明 |
---|---|---|
Motion(运动) | 分配给此状态的动画剪辑 | - |
Speed(速度) | 动画的默认速度 | - |
Multiplier(乘数) | 控制速度的乘数,需勾选 Parameter 选中配合的 float 类型参数才能使用 | - |
Motion Time(运动时间) | 运动的时间,需勾选 Parameter 选中配合的 float 类型参数才能使用,一般是 0 - 1 的数字。使用该参数后动画不会自动播放,需设置参数值才会动,如设置成 0.1,动画就卡在进度播放到 0.1 的位置,在 Update 中不断加大参数值可一帧一帧播完动画 | - |
Mirror(镜像) | 是否为状态生成镜像,仅适用于人形动画,若配合参数使用需选中旁边的 Parameter 关联 bool 类型参数 | - |
Cycle Offset(周期偏移) | 循环偏移时间,若配合参数使用需选中旁边的 Parameter 关联 float 类型参数。如填 0.5,动画就会从中间位置开始播放 | - |
Foot IK(脚步反向动力学) | 是否遵循 Foot IK,适用于人形动画 | - |
Write Defaults(写入默认值) | AnimatorStates 是否为其运动执行未动画化的属性写回默认值,默认勾选 | - |
Solo(单独播放) | 仅播放该过渡,条件都满足的动画优先切换选择了 Solo 的动画 | - |
Mute(静音) | 禁用过渡,就算条件满足也不切换,Solo 和 Mute 一起选择时,Mute 优先执行 | - |
Add Behaviour(添加行为) | 添加状态机行为脚本,之后会专门讲解 | - |
3.4.Animator 窗口中动画过渡设置相关参数
参数 | 描述 | 选项及说明 |
---|---|---|
连线名 | 为动画过渡改名,若不改对应的名字就是”某一状态名”->”某一状态名”,一般不改 | - |
Has Exit Time(是否有退出时间) | 若勾选,当切换动画时,动画一定是播放到下方的 Exit Time(百分比)的时间时才过渡到下一个动画;若希望立刻切换动画,可不勾选该选项 | - |
Exit Time(退出时间) | 当选择上方的 Has Exit Time 时,该值决定了过渡生效的确切时间。该值可以大于 1,若小于 1,比如 0.85,表示当动画播放到了 85%的动画时,就会过渡;若大于 1,比如 4.5,那么动画将循环 4.5 次后过渡到下一个动画 | - |
Fixed Duration(固定持续时间) | 选中后,下方的 Trnaition Duration 过渡持续时间将以秒为单位解读过渡时间;若不选中,则以百分比解读过渡时间 | - |
Transition Duration(s/%)(过渡持续时间) | 从该状态切换到下一状态的过渡动画持续的时间,对应下方两个蓝色箭头包裹区域 | - |
Transition Offset(过渡偏移) | 过渡到目标状态的起始播放的时间偏移。如果是 0 则从要切换到的目标状态开头开始播放,如果是 0.5 则从要切换到的目标状态的一半开始播放,可理解为切入下一个状态的切入点 | - |
Interruption Source(中断源) | 该过渡中断的情况:
| - |
Ordered Interruption(有序中断) | 当前过渡是否可在不考虑顺序的情况下被其它过渡中断:
| - |
Conditions(过渡条件) | 如果没有过渡条件,只会考虑 Exit Time | - |
Can Transition To self(是否可以过渡到自己) | 是否可以过渡到自己,一般取消勾选 | - |
Preview source state(预览源状态) | 预览各种过渡状态,可以查看从任意状态切换到当前状态的过渡效果 | - |
3.5. 动画分层和遮罩
参数 | 描述 | 选项及说明 |
---|---|---|
Weight(权重) | 当动画同时播放且为叠加状态时,根据权重决定叠加的比例 | - |
Mask(动画遮罩) | 该层动画全部受此遮罩影响,需创建遮罩文件并赋值给该参数。遮罩文件可设置不受影响的区域,动画播放时该区域无效果,类似模型文件 Animation 页签下的选项效果,但只影响这一层 | - |
Blending(混合方式) |
| - |
Sync(是否同步其它层) | 主要用于直接从另一个层复制状态过来并在该层中修改。适用于正常状态和受伤状态等动作改变的情况。选择后会多一个 Source Layer 表示要复制哪一层的状态,如复制普通层 1 并修改动画选项为蹲下的待机和走路,调大这一层的权重就会播放蹲下的待机和走路 | - |
Timing(源层) | 当选中 Sync 同步其它层时激活。
| - |
IK Pass(IK 处理) | 反向动力学 | - |
3.6.动画融合树
3.6.1.动画 1D 混合
参数 | 描述 | 选项及说明 |
---|---|---|
Parameter(参数) | 用于控制混合的参数,在参数列表中的参数。蓝色图像可控制 n 个动画的阈值,调整红色指针可在预览窗口查看动画混合情况 | 例如,调整代表 Speed 参数数值的红色指针,0 时动画完全是默认,0.25 是走路和默认结合,0.5 是完全走路,0.75 是走路和跑步结合各一半,1 是完全跑步 |
Motion(关联的动画列表) | 可使用鼠标改变顺序 | - |
Threshold(对应动作的临界阈值) | 当等于这个值时动作权重最大(完全播放该动作),数值范围不定,需取消勾选 Automate Thresholds 才能手动设置 | - |
控制动作的播放速度 | - | - |
是否镜像动作 | - | - |
Automate Thresholds(是否自动设置阈值) | 会在取值范围内平均分,一般取消勾选以手动控制更准确 | - |
Compute Thresholds(计算阈值的方式) | 从动画剪辑的根运动中获取数据,包括 Speed(速度)、Velocity X、Y、Z(xyz 上的分速度)、Angular Speed(Rad 、Deg)(角度或者弧度表示的角速度) | 例如,动画剪辑行走动画时 Speed 速度是 1.5 个单位每秒,慢跑是 2.3 个单位每秒,快跑是 4 个单位每秒,阈值就会根据这些值来进行设置进行混合 |
Adjust Time Scale(调整时间刻度) |
| - |
3.6.2.动画2D 混合
种类 | 描述 | 使用场景 |
---|---|---|
2D Simple Directional(2D 简单定向模式) | 运动表示不同方向时使用 | 比如向前、后、左、右走,若只有一个动作用此模式 |
2D Freeform Directional(2D 自由形式定向模式) | 运动表示不同方向时使用,可在同一方向上有多个运动 | 比如向前跑和走,若一个方向上有走路和跑步用此模式 |
2D Freeform Cartesian(2D 自由形式笛卡尔坐标模式) | 运动不表示不同方向时使用 | 比如向前走不拐弯、向前跑不拐弯、向前走右转、向前跑右转 |
Direct(直接模式) | 自由控制每个节点权重 | 一般用于做表情动作等 |
2D 混合的使用:大体上和 1D 混合相似,只是多关联了一个参数,关联的动画也多设置了一个预制。拖动蓝色框上的红点(类似 1D 混合的红色指针)或混合树的进度条可修改参数值查看效果。
3.7. 3D 动画其他相关知识
3.7.1. 动画子状态机
概念:子状态机是在状态机里包含的另一个状态机。当某一个状态由多个动作状态组合成复杂状态时,如角色技能由跳起、攻击、落下三段动作组成,可将这些动作放在子状态机中。
创建方法:在 Animator Controller 窗口中右键选择 Create Sub-State Machine 来创建。
3.7.2.动画目标匹配
概念:当游戏中角色以某种动作移动后,其手或脚需落在特定位置,如跳过踏脚石、跳跃抓住房梁等。以跳跃动作为例,可使角色跳到实际游戏中不同高度的平面。
实现方式:利用 Unity 中 Animator 的 MatchTarget 函数。步骤为找到动作关键点位置信息(如起跳点、落地点)并传入该函数。
代码示例
if( Input.GetKeyDown(KeyCode.Space) )
{
animator.SetTrigger("Jump");
//Animator中的MatchTarget方法
//自动调整 GameObject 的位置和旋转。
//参数一:目标位置
//参数二:目标角度
//参数三:匹配的骨骼位置
//参数四:位置和角度权重
//参数五:开始位移动作的百分比 这个参数要观察起跳瞬间动画播放了百分之多少
//参数六:结束位移动作的百分比 这个参数要观察落地瞬间动画播放了百分之多少
animator.MatchTarget(targetPos.position, targetPos.rotation, AvatarTarget.RightFoot, new MatchTargetWeightMask(Vector3.one, 1), 0.4f, 0.64f);
}
3.7.3.状态机行为脚本
状态机行为脚本使用方法:新建脚本继承 StateMachineBehaviour 基类,实现特定方法进行状态行为监听,包括 OnStateEnter(进入状态时,第一个 Update 中调用)、OnStateExit(退出状态时,最后一个 Update 中调用)、OnStateIK(OnAnimatorIK 后调用)、OnStateMove(OnAnimatorMove 后调用)、OnStateUpdate(除第一帧和最后一帧,每个 Update 上调用)、OnStateMachineEnter(子状态机进入时调用,第一个 Update 中调用)、OnStateMachineExit(子状态机退出时调用,最后一个 Update 中调用)。
代码示例
// 重写该函数,当进入指定状态时调用
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
// 当前状态名称与所需状态名称相同时输出日志
if (stateInfo.IsName(stateName))
Debug.Log("进入HumanoidIdle状态");
}
// 重写该函数,当退出指定状态时调用
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
// 当前状态名称与指定名称相同时输出日志
if (stateInfo.IsName("HumanoidIdle"))
Debug.Log("退出HumanoidIdle状态");
}
// 重写该函数,当进行动画 IK 计算时调用
public override void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
base.OnStateIK(animator, stateInfo, layerIndex);
}
// 重写该函数,当进行动画更新时每帧调用
public override void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
base.OnStateMove(animator, stateInfo, layerIndex);
}
// 重写该函数,当进行动画更新时每帧调用
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
base.OnStateUpdate(animator, stateInfo, layerIndex);
// 当前状态名称为指定名称时输出日志
if (stateInfo.IsName("HumanoidIdle"))
Debug.Log("处于HumanoidIdle状态");
}
// 重写该函数,当进入状态机时调用
public override void OnStateMachineEnter(Animator animator, int stateMachinePathHash)
{
base.OnStateMachineEnter(animator, stateMachinePathHash);
}
// 重写该函数,当退出状态机时调用
public override void OnStateMachineExit(Animator animator, int stateMachinePathHash)
{
base.OnStateMachineExit(animator, stateMachinePathHash);
}
3.7.4.状态机复用
概念:游戏开发中,多个对象(如多个玩家和怪物)动画状态机行为一致但动作不同时,为避免重复创建状态机浪费时间,状态机复用用于为不同对象使用共同的状态机行为,减少工作量,提升开发效率。
选择依据:状态机行为脚本相对动画事件更准确,但使用稍麻烦,可根据实际需求选择。
状态机复用:在 Project 窗口右键选择 Create -> Animator Override Controller,为 Animator Override Controller 文件在 Inspector 窗口关联基础的 Animator Controller 文件,再关联需要的动画。
`
4.模型导入
4.1.Model模型页签
4.1.1.Scene 场景相关设置
参数 | 描述 | 选项及说明 |
---|---|---|
Scale Factor(缩放系数) | 当模型比例不符合项目预期时,修改此值可改变模型全局比例。Unity 物理系统希望游戏世界 1 米在导入模型文件中为 1 个单位 | - |
Convert Units(转换单位) | 启用后可将模型文件定义的比例转换为 Unity 的比例 | 不同格式比例: - .fbx 、.max 、.jas = 0.01- .3ds = 0.1- .mb 、.ma 、.lxo 、.dxf 、.blend 、.dae = 1 |
Import BlendShapes(导入 BlendShapes) | 是否允许 Unity 随网格导入混合形状,导入含混合形状的网格时用 Skinned MeshRenderer 组件 | 注意: - 导入混合形状需 FBX 文件有平滑组 - 若导入有法线的混合形状,需将 Blend Shape Normals 属性设为 Import 用 FBX 法线信息,或设为 Calculate 让 Unity 计算法线 |
Import Visibility(导入可见性) | 是否导入可见性,开启可从 FBX 文件读取可见性属性 | 一些 3D 建模软件对可见性属性有限制,需根据软件决定是否勾选,一般可不勾选 |
Import Cameras(导入相机) | 是否导入 FBX 文件中的摄像机,Unity 支持部分摄像机属性 | 一般不勾选 |
Import Lights(导入灯光) | 是否导入光源,支持多种光源类型和属性 | 一般不使用 |
Preserve Hierarchy(保持层次结构) | 始终创建一个显示预制体根 | 若多个 FBX 文件含同一层级空根对象,勾选可保留它们,避免层级不匹配影响动画播放 |
Sort Hierarchy By Name(按名称对层级视图排序) | 在层级窗口根据名字排序子物体 | 不启用则保留 FBX 文件定义的层级顺序 |
4.1.2.Meshes 网格相关设置
参数 | 描述 | 选项及说明 |
---|---|---|
Mesh Compression(网格压缩) | 设置压缩比减小网格文件大小,提高压缩比降低网格精度 | - Off:不压缩 - Low:低压缩比 - Medium:中等压缩比 - High:高压缩比 |
Read/Write Enabled(读/写已启用) | 是否开启读写网格信息 | 开启:Unity 传网格数据给 GPU 后,CPU 保留可寻址内存,可通过代码访问处理;关闭:传数据给 GPU 后,删除 CPU 可寻址内存中网格数据。开启增加内存占用,关闭节约运行时内存。开启场景: - 需要在代码中读写网格数据 - 需要运行时合并网格 - 需要使用网格碰撞器 - 需要运行时用 NavMesh 构建组件烘焙 NavMesh 等 |
Optimize Mesh(优化网格) | 确定三角形在网格中列出的顺序以提高 GPU 性能 | - Nothing:无优化 - Everything:对顶点及多边形顶点索引重新排序 - Polygon Order:仅对多边形重新排序 - Vertex Order:仅对顶点重新排序 |
Generate Colliders(生成碰撞器) | 启用后自动附加网格碰撞器导入网格 | 建议不移动的环境几何体开启,移动的几何体不开启 |
4.1.3.Geometry 几何体相关设置
参数 | 描述 | 选项及说明 |
---|---|---|
Keep Quads(保留四边形) | 启用后,Unity 不将 4 个顶点的多边形转为三角形 | 使用曲面细分着色器时可能需启用,顶点数超四的多边形始终转为三角形。有四边形和三角形的网格,Unity 会创建两个子网格分离它们 |
Weld Vertices(焊接顶点) | 合并空间中共享相同位置且属性相同的顶点 | 开启可减少网格顶点计数优化网格,除非想保留重复顶点用于代码处理,一般开启 |
Index Format(索引格式) | 网格索引缓冲区的大小 | 一般选 16bits,Auto 可能默认选 16bits,必要时用 32bit,16bits 通用且节约内存 |
Legacy Blend Shape Normals(旧版混合形状法线) | 启用后基于 Smoothing Angle 值计算法线 | - |
Normals(法线) | 定义如何计算法线 | - Import:从文件导入法线,文件无则用 Calculate 模式计算 - Calculate:根据 Normals Mode、Smoothness Source 和 Smoothing Angle 属性计算 - None:不计算法线 |
Blend Shape Normals(混合形状法线) | 定义如何为混合形状计算法线,仅当 Legacy Blend Shape Normals 禁用时出现 | - |
Normals Mode(法线模式) | 计算法线的模式,仅当 Normals 设为 Import 或 Calculate 时出现 | - Unweighted Legacy:2017.1 版本前计算法线的方式,之前导入的 FBX 模型默认设置 - Unweighted:法线不加权重 - Area Weighted:法线按图面面积加权重 - Angle Weighted:法线按每个图面上的顶角加权重 - Area And Angle Weighted:法线按图面面积和顶角加权重,默认选项 |
Smoothness Source(平滑度源) | 确定平滑的方式,仅当 Legacy Blend Shape Normals 禁用时出现 | - Prefer Smoothing Groups:尽可能用模型文件中的平滑组 - From Smoothing Groups:仅用模型文件中的平滑组 - From Angle:用 Smoothing Angle 值确定平滑边 - None:不拆分硬边的任何顶点 |
Smoothing Angle(平滑角度) | 控制是否为硬边拆分顶点,值越大顶点越少 | 仅当 Normals 设为 Calculate 时可用,仅用于非常光滑或复杂的模型,否则建议在 3D 建模软件中手动平滑后导入 |
Tangents(切线) | 定义如何导入或计算顶点切线,仅当 Normals 设为 Calculate 或 Import 时可用 | - Import:Normals 为 Import 时,从 FBX 文件导入顶点切线,无切线则无法用法线贴图着色器 - Calculate Legacy:用旧版算法计算切线 - Calculate Legacy With Split Tangents:用旧版算法计算切线并在 UV 图表上拆分,网格接缝影响法线贴图光照时使用 - Calculate Mikktspace:用米克特空间计算切线 - None:不导入顶点切线,无切线则无法用法线贴图着色器 |
Swap UVs(交换 UVs) | 在网格中交换 UV 通道,漫反射纹理使用光照贴图中的 UV 时使用 | - |
Generate Lightmap UVs(生成光照贴图 UVs) | 为光照贴图创建第二个 UV 通道 | - |
4.2.Rig操纵骨骼页签
4.2.1. Animation Type(动画类型)
类型 | 描述 |
---|---|
None(不存在动画) | 主要用于环境静态模型,如石头等。 |
Humanoid(人形模型) | 一般有头和四肢(一个头、两条腿、两只手)的模型视为人形模型,需要使用 Avatar 化身系统,绑定人体主要关节的映射关系。 - Avatar Definition(选择获取 Avatar 定义的位置): - No Avatar:没有化身系统信息。 - Create From This Model:根据此模型创建 Avatar 化身信息。 - Copy from Other Avatar:指向另一个模型上设置的 Avatar 化身信息,需指定 Source(复制另一个具有相同骨架的 Avatar 化身信息以导入其动画剪辑)。 - Skin Weights(蒙皮权重):设置影响单个顶点的最大骨骼数量。 - Standard(4 Bones)标准:使用最多 4 个骨骼产生影响,出于性能考虑,建议使用此设置。 - Custom 自定义:可设置自定义的最大骨骼数,选择后会出现以下选项: - Max Bones/Vertex:定义每个顶点的最大骨骼个数,值越大性能消耗越大。 - Max Bone Weight:设置考虑骨骼权重的最低阈值,权重计算时将忽略小于此值的内容。 - Optimize Game Objects(优化游戏对象):在 Avatar 化身系统和 Animator 动画组件中删除和存储所导入角色的游戏对象骨骼层级信息。启用后会出现 Extra Transforms to Expose 选项,角色将使用 Unity 动画系统的内部骨架,可提高动画角色的性能,一般不勾选。 - Extra Transforms to Expose(要暴露的额外变换):要公开的骨骼层级,可在下方打钩公开该骨骼层级信息。有放大镜(通过名称搜索对应骨骼信息)、Toggle All(全选或者反选)、Collapse All(全部折叠)、Expand All(全部展开)等操作。 |
Generic(通用模型,非人形模型) | 不是标准的人形模型,形状任意,如可能有 8 只腿、两个头等。这种模型主要需要设置骨骼根节点。Root Node(根节点):选择用于此 Avatar 的根节点的骨骼(仅当选择 Create From This Model 才会出现)。 |
Legacy(旧版动画类型) | 与 Unity3.x 及更早版本导入和使用动画,一般不使用。 |
4.2 2. Muscles&Settings(肌肉与设置)
- Muscle Group Preview(肌肉群预览):可预览不同姿势的旋转变化,观察之前的关联映射关系是否合理,主要起预览作用,可拖拽关节点查看关节旋转效果。
- Per - Muscle Settings(肌肉设置):用于设置各骨骼在旋转时的范围限制,避免在极限角度出现奇怪效果,可单独设置限制范围。
- Additional Settings(高级设置):可以设置手脚的扭转和伸展值,一般不修改。其中 Translation DoF 比较重要:
- 如果启用,将启用人形角色的移动动画,可进行骨骼的位置移动,但可能导致其他骨骼拉长。
- 如果禁用,Unity 仅使用旋转对骨骼进行动画化。启用后会提升性能消耗,因为动画需要执行额外步骤来重定向人形动画,除非动画包含角色某些骨骼的动画式移动,否则一般禁用。
- Muscles 肌肉下拉框:可重置所有设置。
4.3.Animation动画页签
4.3.1.导入相关参数设置
参数 | 描述 | 选项及说明 |
---|---|---|
Import Constraints(导入约束) | 从此资源导入约束 | 启用后,Unity 会自动添加相应的约束组件并关联到正确的游戏对象 |
Import Animation(导入动画) | 从此资源导入动画 | 禁用时,其下方相关设置都不可用,且不会导入任何动画 |
Bake Animations(烘焙动画) | 通过反向动力学(IK)或模拟创建的动画以便推进运动关键帧,仅用于 Maya、3Dmax 和 Cinema4D 文件 | - |
Anim.Compression(动画压缩类型) | 导入动画时使用的压缩类型 |
|
Rotation Error(旋转错误) | 设置旋转曲线压缩容错度(百分比),即原始旋转值和减小值之间的最小角度 | 仅在 Keyframe Reduction 或 Optimal 压缩时可用,若原始值和消减值之间的差小于原始值乘以容错百分比,会删除关键帧 |
Position Error(位置错误) | 设置位置曲线压缩容错度(百分比) | 同 Rotation Error 的使用条件 |
Scale Error(缩放错误) | 设置缩放曲线压缩容错度(百分比) | 同 Rotation Error 的使用条件 |
Animated Custom Properties(动画自定义属性) | 导入指定为自定义用户属性的任何 FBX 属性 | - |
4.3.2.动画剪辑选择与属性设置
属性 | 描述 | 选项及说明 |
---|---|---|
动画剪辑名称 | 可编辑修改,修改后需应用,且剪辑列表也会改变 | - |
时间轴 |
| 可在时间轴中定义每个动画剪辑的帧范围 |
Loop Time(循环时间) | 播放动画剪辑时是否循环播放,到结尾时重新开始 | 循环动作即结束动作到开始动作无缝循环运动 |
Loop Match(循环匹配) | 结束动作和开始动作循环匹配的状态,绿色表示成功,红色表示失败 | - |
Cycle Offset(周期偏移) | 循环动画在其他时间开始时的周期偏移 | - |
Root Transform Rotation(根变换旋转) | 与根位置的角度相关 |
|
Root Transform Position(Y)(根变化位置(Y)) | 根垂直位置(Y 轴方向) |
|
Root Transform Position(XZ)(根变化位置(XZ)) | 根水平位置(XZ 平面) |
|
Mirror(镜像) | 在此剪辑中进行左右镜像(仅 Humanoid 人形动画类型才显示) | - |
Additive Reference Pose(叠加型参考动作) | 启用后可以设置附加动画层基础参考姿势的帧,在时间轴中可见蓝色标记 |
|
4.4 Materials材质纹理页签
参数 | 描述 | 选项及说明 |
---|---|---|
Material Creation Mode(材质创建模式) | 定义 Unity 为模型生成或导入材质的方式 |
|
sRGB Albedo Colors(sRGB 反照率颜色) | 是否在伽马空间中使用反射率颜色 | 对于使用线性颜色控件的项目,禁用此选项。若 Material Creation Mode 选择的是 Import via MaterialDescription(Experimental),该属性不可用 |
Location(位置) | 定义访问材质和纹理的方式 |
|
Extract Textures/Materials(纹理/材料) | 当 Location 位置选择 Use Embedded Materials 后出现的内容,用于提取导入资源中嵌入的所有材质和纹理 | 如果没有需要提取的子资源,这两个按钮会显示为灰色 |
Naming(命名) | 定义材质的命名规则 |
|
Search(搜索) | 定义在使用 Naming 选项定义的名称时查找现有材质的位置规则 |
|
EthanWhite(重新映射的材质) | 如果找到了,Unity 会自动关联;如果没有找到,可手动进行关联 | - |
5.CharacterController角色控制器
5.1.角色控制器的概念
角色控制器是一种用于控制角色的组件,它使角色受制于碰撞,但不会像刚体那样产生一些奇怪的表现。例如,使用刚体判断碰撞时,角色可能在斜坡上往下滑动,或者在碰撞时被撞飞等,而角色控制器能让角色表现得更加稳定。Unity 提供了专门的角色控制器组件来实现这一功能。
注意:添加角色控制器后,无需再添加刚体,并且它能检测碰撞函数和触发器函数。
5.2.角色控制器的使用
使用角色控制器时,建议取消 Animator 组件上的根运动,以避免与角色控制器的控制产生冲突,确保角色运动的稳定性和可控性。
5.3.角色控制器组件参数
参数 | 描述 | 说明 |
---|---|---|
Slope Limit(斜度限制) | 坡度度数限制,大于该值的斜坡角色无法上去 | - |
Step Offset(每步偏移量) | 台阶偏移值,单位为米,低于这个值的台阶角色才能上去,且该值不能大于角色控制器的高度 | - |
Skin Width(蒙皮宽度) | 皮肤的宽度,即两个碰撞体可以穿透彼此的最大宽度。较大的值可减少抖动,较小的值可能导致角色卡住,建议设置为半径的 10%,通俗理解为角色可以和刚体穿模的程度 | - |
MinMoveDistance(最小移动距离) | 大多数情况下为 0,可用于减少抖动 | - |
5.4.角色控制器代码控制
CharacterController.isGrounded 变量:用于判断在上次移动期间 CharacterController 是否接触地面。
//CharacterController中的isGrounded变量 是否接触了地面
//在上次移动期间 CharacterController 是否接触地面?
if ( characterController.isGrounded )
{
print("接触地面了");
}
CharacterController.SimpleMove 方法:使角色受重力作用进行移动,以指定的速度移动角色。
//CharacterController中的SimpleMove方法 受重力作用的移动
//以 speed 移动该角色。
characterController.SimpleMove(Vector3.forward * 10 * Time.deltaTime);
CharacterController.Move 方法:让角色进行不受重力作用的移动,为 GameObject 的移动提供附加的 CharacterController 组件。
//CharacterController中的Move方法 不受重力作用的移动
//为 GameObject 的移动提供附加的 CharacterController 组件。
characterController.Move(Vector3.forward * 10 * Time.deltaTime);
5.5.碰撞和触发检测函数
OnControllerColliderHit 函数:当角色控制器与别的碰撞器产生碰撞时调用该函数。
//当角色控制器想要判断和别的碰撞器产生碰撞时 使用该函数
private void OnControllerColliderHit(ControllerColliderHit hit)
{
print("角色碰撞器发生碰撞"+hit.collider.gameObject.name);
}
OnCollisionEnter 方法:对于角色控制器无效,不会被调用。
//OnCollisionEnter方法对角色控制器没用
//private void OnCollisionEnter(Collision collision)
//{
// print("碰撞触发");
//}
OnTriggerEnter 方法:角色控制器可以检测触发器,当进入触发器时该方法会被调用。
private void OnTriggerEnter(Collider other)
{
print("触发器触发");
}
6.导航寻路系统
6.1.导航网格生成
Object 场景对象设置页签:设置参与寻路烘焙的对象。
参数 | 描述 | 选项及说明 |
---|---|---|
Sceme Filter(场景过滤器) | 配合 Hierarchy 窗口使用,筛选对象 |
|
Navigation Static(导航静态物体开关) | 若想对对象进行地形数据生成,需打开此选项,打开对象上的这个开关实际是打开静态下的导航静态 | - |
Generate OffMeshLinks(生成网格连接点开关) | 用于两个地形断开但想实现跳跃过去的情况,打开对象上的这个开关实际是打开静态下的网格连接静态 | - |
Navigation Area(导航区域选择) | 配合 Areas 页签使用 | - |
Bake 导航数据烘焙页签:设置寻路网格具体信息,点击烘焙后,场景中生成的蓝色部分为可行走区域,需设置有对象为导航静态才能烘焙成功。 |
参数 | 描述 | 说明 |
---|---|---|
Agent Radius(代理半径) | 决定烘焙边缘精确度,控制平台可行走区域和边缘可行走区域,可理解为人物半径 | 半径越小,烘焙出来能走的地方越多 |
Agent Height(代理高度) | 决定烘焙高度精确度,控制拱桥是否可以穿越,可理解为人物高度 | 高度越小,能穿过的拱桥越多,烘焙出来能走的地方越多 |
Max Slope(最大坡度) | 斜坡度数,决定斜坡是否可以行走,影响斜坡的烘焙 | 若场景里的斜坡大于最大坡道,角色将无法上去 |
Step Height(步高) | 最小楼梯高度,决定台阶是否可以行走,影响台阶的烘焙 | 若场景里的台阶高度大于步高,角色将无法上去 |
Generated off mesh Links(生成分离网格链接) | 生成非网格连接,用于两个分开的网格之间的连接相关设置,需在 Object 场景对象设置页签中打开 Generate OffMeshLinks 生成网格连接点开关,且注意下面两个变量也要设置,否则可能不生成 | - |
Drop Height(掉落高度) | 角色可以从这个高度掉下来 | - |
Jump Distance(跳跃距离) | 决定不同平面上的跳跃距离,小于这个距离内角色可以跳过 | - |
Advanced(高级) |
| - |
Areas 导航地区页签:设置对象的寻路消耗,配合 Object 页签使用。
参数 | 描述 | 说明 |
---|---|---|
Name(区域名字) | 区域的名称 | - |
Cost(成本 寻路消耗) | 寻路消耗,可以自己新加一个导航区域,然后去 Object 页签选择 | 调高寻路消耗成本会影响寻路结果,例如将水的寻路消耗调高,对象就会绕着水路走 |
Agents 代理页签:设置寻路代理信息,可单独设置寻路对象。
6.2.NavMeshAgent
6.2.1.NavMeshAgent 组件参数
Agent Type(代理类型):配合 Agents 页签使用。
Base Offset(基础偏移值):相对对象轴心点的高度偏移,即改变圆柱体位置。
Steering(转向 移动设置)
参数 | 描述 | 说明 |
---|---|---|
Speed(寻路时的最大移动速度) | 寻路时的最大移动速度(世界单位/秒) | - |
Angular Speed(寻路时转身的最大旋转速度) | 寻路时转身的最大旋转速度(度/秒) | - |
Acceleration(最大加速度) | 最大加速度(世界单位/平方秒) | - |
Stopping Distance(停止距离) | 当靠近目标点多少距离时,停止运动 | - |
Auto Braking(自动制动) | 启用后,当到达目标时将减速,若存在连续移动(如巡逻移动)建议不要开启该选项 | - |
Obstacle Avoidance(障碍躲避 避障设置)
参数 | 描述 | 说明 |
---|---|---|
Radius(半径) | 用于计算障碍物和其它寻路对象之间的碰撞 | - |
Height(高度) | 通过头顶障碍物时用于计算高度间隙使用 | - |
Quality(障碍躲避品质) | 越高躲避障碍越准确,但性能消耗较大。若不想主动避开其它动态障碍,可设置为无,则只会解析碰撞 | - |
Priority(优先级) | 0~99,避障时,数字较小的障碍物表示较高的优先级,优先级低的会忽略避障 | - |
Path Finding(寻路 路径寻找规则)
参数 | 描述 | 说明 |
---|---|---|
Auto Traverse OffMesh Link(自动通过分离网格连接) | 是否开启自动遍历网格外的其它网格连接,若要自定义判断,则关闭此功能 | - |
Auto Repath(自动重新寻路) | 是否开启自动重设路线,开启后,当到达路径后段时会再次尝试寻路,当没有到达目标的路径时,会生成一条到达与目标位置最近的可达点,默认勾选 | - |
Area Mask(寻路时考虑的区域) | 若寻路时不想考虑某些区域,则取消选中,常见于塔防游戏 | - |
6.2.2.NavMeshAgent 代码控制
常用内容
方法/变量 | 描述 | 代码示例 |
---|---|---|
NavMeshAgent.SetDestination 方法 | 自动寻路设置目标点,传入 Vector3 变量,设置或更新目标,从而触发新路径计算 | navMeshAgent.SetDestination() |
NavMeshAgent.isStopped 变量 | 停止寻路,此属性持有导航网格代理的停止或恢复条件 | navMeshAgent.isStopped = true; |
不常用内容
方法/变量 | 描述 | 代码示例 |
---|---|---|
NavMeshAgent.speed 变量 | 遵循路径时的最大移动速度 | print(navMeshAgent.speed); |
NavMeshAgent.acceleration 变量 | 代理遵循某一路径时的最大加速度,以单位/秒² 表示 | print(navMeshAgent.acceleration); |
NavMeshAgent.angularSpeed 变量 | 遵循路径时的最大回转速度(以 deg/ s 为单位) | print(navMeshAgent.angularSpeed); |
NavMeshAgent.hasPath 变量 | 代理当前是否有路径(只读) | if ( navMeshAgent.hasPath ) { } |
NavMeshAgent.destination 变量 | 代理目标点,可以设置也可以得到,获取代理在世界坐标系单位中的目标或尝试设置代理在其中的目标 | print(navMeshAgent.destination); |
NavMeshAgent.path 变量 | 获取和设置当前路径的属性 | print(navMeshAgent.path); |
NavMeshAgent.pathPending 变量 | 路径是否在计算中,是否正在计算过程中而尚未就绪的路径(只读) | if ( navMeshAgent.pathPending ) { } |
NavMeshAgent.pathStatus 变量 | 当前路径的状态(完整、部分或无效) | print(navMeshAgent.pathStatus); |
NavMeshAgent.updatePosition 变量 | 获取或设置变换位置是否与模拟的代理位置同步,默认值为 true | navMeshAgent.updatePosition = true; |
NavMeshAgent.updateRotation 变量 | 代理是否应该更新变换方向 | navMeshAgent.updateRotation = true; |
NavMeshAgent.velocity 变量 | 获取 NavMeshAgent 组件的当前速度,或者设置一个速度来手动控制代理 | print(navMeshAgent.velocity); |
NavMeshAgent.CalculatePath 方法 | 计算到指定点的路径并存储生成的路径 | NavMeshPath navMeshPath = new NavMeshPath();if(navMeshAgent.CalculatePath(Vector3.zero, navMeshPath) ){} |
NavMeshAgent.SetPath 方法 | 为此代理分配一条新路径 | if (navMeshAgent.SetPath(navMeshPath)) { } |
NavMeshAgent.ResetPath 方法 | 清除当前路径 | navMeshAgent.ResetPath(); |
NavMeshAgent.Warp 方法 | 将代理调整至指定的位置 | navMeshAgent.Warp(Vector3.zero); |
6.3.OffMeshLink
参数 | 描述 | 选项及说明 |
---|---|---|
Start(起始点) | 连接的起始位置 | - |
End(结束点) | 连接的结束位置 | - |
Cost Override(成本覆盖) | 覆盖消耗值。若为负数或 0,则使用所属 Area 区域中的消耗值,即两岸上烘焙区域的寻路成本;若为正数,则使用 Area 区域寻路消耗值乘以该正数作为该连接点的寻路消耗,可自定义连接点的寻路消耗 | 主要用于解决当存在“步行”路径和连接点都能到达某一目标时的路径选择问题。例如有两个连接桥,可通过比较该参数,优先选择成本消耗更低的路径 |
Bi Directional(双向) | 是否开启双向连接点。开启后连接可从 Start 到 End,也能从 End 到 Start;关闭时则只能从 Start 到 End | - |
Activated(已激活) | 是否启用该连接点。若关闭,自动寻路时该连接点相当于失效 | - |
Auto Update Positions(是否自动更新位置) | 如果启用,当开始和结束位置改变时,导航网格也将更新;如果不启用,即使改变了开始和结束位置,仍会按照刚开始的位置进行计算,主要用于运行时修改路径 | - |
6.4.NavMeshObstacle
参数 | 描述 | 选项及说明 |
---|---|---|
Shape(动态障碍的形状) | 动态障碍物的形状类型 |
|
Carve(切割 是否开启雕刻功能) | 是否开启雕刻功能。开启后,障碍物会在导航网格中挖一个孔,生成对应的网格信息,使该区域被认为无法前往;若动态障碍物是固定不动的,建议开启,如门、木桶、栅栏等;若动态障碍物是频繁移动的,建议不开启,如汽车和玩家 | - |
Move Threshold(移动阈值) | 当障碍物移动超过该距离时,会被认为处于移动状态,进而更新移动的孔 | - |
Time To Stationary(静止时间) | 障碍物作为静止状态需要等待的时间,单位为秒。当静止时间超过该值,才会被认为真正静止 | - |
Carve Only Stationary(仅在静止时切割) | 只有在障碍物处于静止状态时才会计算孔 | - |
四、Unity进阶
1.InputSystem
开启方法:File——>Build Setting——>Player Setting——>Other——>Active Input Handling
1.1.代码检测输入
1.1.1.键盘输入
获取方式 | 操作检测 | 说明 |
---|---|---|
using UnityEngine.InputSystem; <br> Keyboard keyBoard = Keyboard.current; | 单个按键按下 | 通过keyBoard.具体按键.wasPressedThisFrame 判断,如if (Keyboard.current.spaceKey.wasPressedThisFrame) 可检测空格键按下 |
单个按键抬起 | 利用keyBoard.具体按键.wasReleasedThisFrame ,例如if (Keyboard.current.dKey.wasReleasedThisFrame) 检测D键抬起 | |
单个按键长按 | 使用keyBoard.具体按键.isPressed ,像if (Keyboard.current.spaceKey.isPressed) 检测空格长按状态 | |
文本输入监听 | lambda表达式:keyBoard.onTextInput += (c) => {print("通过lambda表达式" + c);}; 普通函数:先定义 private void TextInput(char c) ,再keyBoard.onTextInput += TextInput; | |
任意键按下 | if (Keyboard.current.anyKey.wasPressedThisFrame) ,但无法得知具体按下的键 |
1.1.2.鼠标输入
获取方式 | 操作检测 | 说明 |
---|---|---|
Mouse mouse = Mouse.current; | 各键位按下 | 以左键为例,if (Mouse.current.leftButton.wasPressedThisFrame) 判断左键按下 |
各键位抬起 | 如if (Mouse.current.leftButton.wasReleasedThisFrame) 检测左键抬起 | |
各键位长按 | 例如if (Mouse.current.rightButton.isPressed) 检测右键长按 | |
当前位置 | Mouse.current.position.ReadValue() ,原点是左下角,值为屏幕最大分辨率 | |
两帧偏移向量 | Mouse.current.delta.ReadValue() ,获取鼠标两帧间移动向量 | |
滚轮方向向量 | Mouse.current.scroll.ReadValue() ,往上滚大于0,往下滚小于0 |
1.1.3.触屏输入
获取方式 | 操作检测 | 说明 |
---|---|---|
Touchscreen touchscreen = Touchscreen.current; 使用前判空: if (touchscreen == null) return; | 手指数量 | print(touchscreen.touches.Count) 输出当前触屏手指数量 |
单个触屏手指 | touchscreen.touches[0] 获取指定索引的手指信息 | |
遍历所有触屏手指 | foreach (var item in touchscreen.touches) 遍历所有触屏手指 | |
手指按下 | if (touchControl.press.wasPressedThisFrame) ,touchControl 为指定手指对象 | |
手指抬起 | if (touchControl.press.wasReleasedThisFrame) 检测手指抬起 | |
手指长按 | if (touchControl.press.isPressed) 判断手指长按状态 | |
点击手势 | if(touchControl.tap.isPressed) 检测手指点击 | |
连续点击次数 | print(touchControl.tapCount) 输出手指连续点击次数 | |
手指位置 | print(touchControl.position.ReadValue()) 获取当前手指位置 | |
首次接触位置 | print(touchControl.startPosition.ReadValue()) 得到手指第一次接触时位置 | |
接触区域大小 | touchControl.radius.ReadValue() 读取手指接触区域半径大小 | |
偏移位置 | touchControl.delta.ReadValue() 获取手指偏移位置 | |
手指状态 | UnityEngine.InputSystem.TouchPhase touchPhase = touchControl.phase.ReadValue(); 通过 switch 语句判断:switch (touchPhase) { //无 case UnityEngine.InputSystem.TouchPhase.None: break; //开始接触 case UnityEngine.InputSystem.TouchPhase.Began: break; //移动 case UnityEngine.InputSystem.TouchPhase.Moved: break; //结束 case UnityEngine.InputSystem.TouchPhase.Ended: break; //取消 case UnityEngine.InputSystem.TouchPhase.Canceled: break; //静止 case UnityEngine.InputSystem.TouchPhase.Stationary: break; default: break; } |
希望这个更新后的表格能满足你的需求。如果你还有其他问题,请随时告诉我。
1.1.4.手柄输入
获取方式 | 操作检测 | 说明 |
---|---|---|
Gamepad gamePad = Gamepad.current; 使用前判空: if (gamePad == null) return; | 左摇杆方向向量 | print(gamePad.leftStick.ReadValue()) ,右和上是正方向 |
右摇杆方向向量 | print(gamePad.rightStick.ReadValue()) | |
左摇杆按下 | if (gamePad.leftStickButton.wasPressedThisFrame) 判断左摇杆按下 | |
左摇杆抬起 | if (gamePad.leftStickButton.wasReleasedThisFrame) 检测左摇杆抬起 | |
左摇杆长按 | if (gamePad.leftStickButton.isPressed) 检测左摇杆长按 | |
方向键(以左方向键为例) | 按下:if (gamePad.dpad.left.wasPressedThisFrame) 抬起: if (gamePad.dpad.left.wasReleasedThisFrame) 长按: if (gamePad.dpad.left.isPressed) | |
右侧按键(以北向按钮为例) | gamePad.buttonNorth ,按下检测如if (Gamepad.current.buttonNorth.wasPressedThisFrame) ,也可按具体名字如gamePad.triangleButton 等监听 | |
中央按键(开始键) | gamePad.startButton ,按下检测if (Gamepad.current.startButton.wasPressedThisFrame) | |
中央按键(选择键) | gamePad.selectButton ,按下检测if (Gamepad.current.selectButton.wasPressedThisFrame) | |
肩部按键(左侧前方) | gamePad.leftShoulder ,按下检测if (Gamepad.current.leftShoulder.wasPressedThisFrame) | |
肩部按键(左侧后方) | gamePad.leftTrigger ,按下检测if (Gamepad.current.leftTrigger.wasPressedThisFrame) |
1.1.5.其他输入
设备类型 | 说明 | 学习方式 |
---|---|---|
Joystick(摇杆) | 用于输入操作 | 查看官方文档或类内部成员,了解属性和方法 |
Pen(电子笔) | 实现特定输入 | 同上 |
Sensor(传感器) | 包含陀螺仪(UnityEngine.InputSystem.Gyroscope )、重力传感器等 | 查看官方文档,或通过代码示例如UnityEngine.InputSystem.Gyroscope gyroscope = UnityEngine.InputSystem.Gyroscope.current; gyroscope.angularVelocity.ReadValue(); ,查看类内部成员使用 |
1.2.InputAction
以下是对上述“InputAction”相关内容整理的表格,涵盖了InputAction的定义、参数设置、不同类型的输入绑定、使用方法以及相关设置等方面:
1.2.1.InputAction参数设置
设置项 | 详情 |
---|---|
Actions输入动作设置 | 设置检测的输入类型 |
Action Type(动作类型) | Value :用于状态连续更改的输入,多个设备绑定时只发送最受控制设备的输入Button :每次按下时触发的ActionPass Through :和Value 类似,多个设备绑定时发送所有设备的输入 |
Control Type(控制类型) | 选择类型后会筛选输入设备,如Vector2 只能选返回Vector2 变量类型的设备(手柄摇杆、鼠标位置等),Button 只能选按钮返回值设备(鼠标左键、手柄按键等),包括Any 、Analog 、Axis 、Bone 、Digital 、Double 、Dpad 、Eyes 、Integer 、Quaternion 、Stick 、Touch 、Vector2 、Vector3 等 |
Interactions相互作用设置 | 用于特殊输入(长按、多次点击等),满足条件时触发行为,有started (开始)、performed (触发)、canceled (结束)三个事件 |
相互作用设置参数 | Hold :长按操作,按下触发started ,按住时间大于等于Hold Time 触发performed ,否则触发canceled Tap :点击操作,按下触发started ,在Max Tap Duriation 时间内松开触发performed ,否则触发canceled SlowTap :类似Hold ,按住时间大于等于Max Tap Duriation ,松开时触发performed MultiTap :多次点击操作,Tap Count 为点击次数,Max Tap Spacing 为点击间隔,Max Tap Duration 为每次点击持续时间,满足条件触发performed Press :类似按钮操作,Trigger Behavior 有Press Only (按下触发started 和performed ,不触发canceled )、Release Only (按下触发started ,松开触发performed )、Press And Release (按下和松开都触发started 和performed ,不触发canceled )、Press Point (利用按钮浮点值区分按下状态) |
Processors值处理加工设置 | Clamp :将输入值钳制到[min..max] 范围Invert :反转控件值(乘以-1)Invert Vector 2 :反转Vector2 轴的值Invert Vector 3 :反转Vector3 轴的值Normalize :将输入值规格化为[0..1] 或[-1..1] Normalize Vector 2 :将输入向量规格化为单位长度Normalize Vector 3 :将输入向量规格化为单位长度Scale :将输入值乘以系数Scale Vector 2 :沿x 、y 轴乘以相应值Scale Vector 3 :沿x 、y 、z 轴乘以相应值 |
死区设置 | Axis Deadzone :缩放控件值,使绝对值小于最小值为0,大于最大值为1或-1,避免无意输入和确保最大值Stick Deadzone :缩放Vector2 控件值,幅值小于最小值为(0,0) ,大于最大值规格化为长度1 |
1.2.2.InputAction输入绑定类型
绑定类型 | 详情 |
---|---|
Add Binding | 添加单按键输入绑定,如鼠标左右键按下 |
Add Positive\Negative Binding Or Add 1D Axis Composite | 添加1D轴组合(类似水平竖直热键,返回-1~1值),参数有Negative (负面按键)、Positive (正向按键)、Composite Type (复合类型)、MinValue (最小值)、MaxValue (最大值)、Which Side Wins (同时按下处理方式,Neither :取中间值,Positive :取maxValue ,Negative :取minValue ) |
Add Up\Down\Left\Right Composite Or Add 2D Vector Composite | 添加2D向量组合(类似水平竖直热键组合,Vector 的x 、y 表示两个轴),参数有Up 、Down 、Left 、Right 、Composite Type (复合类型)、Mode (处理模式,Analog :模拟值,Digital Normalized :单位化向量,Digital :未单位化向量) |
Add Up\Down\Left\Right\Forward\Backward Composite | 添加3D向量组合,比2D多一维参数,需关联多两个键 |
Add Button With One Modifier Composite | 添加带有一个复合修改器的按钮(双组合键,如Ctrl+C ),参数有Modifier (复合输入内容)、Button (输入内容) |
Add Button With Two Modifier Composite | 添加带有两个复合修改器的按钮(三组合键,如Ctrl+K+U ),参数有Modifier (两个复合输入内容)、Button (输入内容) |
1.2.3.InputAction使用方法
操作 | 详情 |
---|---|
启用输入检测 | move.Enable(); |
操作监听 - 开始操作 | move.started += StartedTestFun; private void StartedTestFun(InputAction.CallbackContext context) { print("开始事件调用"); } |
操作监听 - 真正触发 | move.performed += (context) => { print("触发事件调用"); } |
操作监听 - 结束操作 | move.canceled += (context) => { print("结束事件调用"); } |
关键参数CallbackContext | 可获取当前状态(context.phase ,如Disabled 、Waiting 、Started 、Performed 、Canceled )、动作行为信息(context.action.name )、控件(设备)信息(context.control.name )、获取值(context.ReadValue<float> )、持续时间(context.duration )、开始时间(context.startTime ) |
1.2.4.InputAction特殊设置及系统设置
设置项 | 详情 |
---|---|
特殊输入设置 | 可在Interactions 中为整个动作或单个设备设置特殊输入条件,如长按时间等;可点击创建InputSystem 默认值设置文件并修改 |
Input System Package设置 | UpdateMode :更新模式(Process Events In Dynamic Update 、Process Events In Fixed Update 、Process Events Manually )Background Behavior :后台行为(Reset And Disable Non Background Devices 、Reset And Disable All Devices 、Ignore Focus 、Filter Noise on .current 、Compensate Orientation )Default Deadzone Min :默认死区最小值Default Deadzone Max :默认死区最大值Default Button Press Point :默认按钮按下点Button Release Threshold :按钮释放阈值Default Tap TIme :默认点击时间Default Slow Tap Time :默认慢速点击时间Default Hold Time :默认保持时间Tap Radius :点击半径MultTap Delay TIme :多次点击延迟时间Supported Devices :可设置支持的设备,不设置则支持所有可识别设备,设置后缩小编辑器显示范围并避免无关设备输入Motion Usage :动作使用Description :描述Play Mode Input Behavior :播放模式输入行为(Pointers And Keyboards Respect Game View Focus 、All Devices Respect Game View Focus 、All Device Input Always Goes To Game View ) |
以下是根据你提供的内容整理的关于输入配置文件的表格: |
1.2.5.InputActions输入操作配置文件
类别 | 详情 |
---|---|
定义 | 输入系统中是 InputAction 的集合,记录想要处理的行为和动作(InputAction 相关信息),可自定义 InputAction (如开火、移动、旋转等)并关联对应的输入动作,与 PlayerInput 关联后,PlayerInput 自动解析文件,触发输入动作时以分发事件形式通知执行行为 |
创建方式 | 在 Project 窗口右键选择 Create 创建 InputActions 配置文件,文件后缀为 .inputactions ,本质是 json 文件 |
编辑方式 | 双击创建出的文件弹出配置窗口进行配置,每次更改后需点击保存配置或勾选自动保存 |
配置窗口参数 | ActionMaps 行动地图窗口:可理解为行为分组配置,能配置多套操作规范,可右键或点击加号创建新配置、移除等 Actions 输入动作窗口:在此可通过加号或右键创建各种 InputAction ,无需在代码中声明变量,可直接添加键盘配置Properties 输入操作绑定的输入属性:与普通 InputAction 点击齿轮的选项相同工具栏:提供保存、搜索等功能按键 |
设置编辑器显示的控制方案 | 选项:Gamepad (手柄)、Joystick (摇杆)、KeyboardMouse (键盘鼠标)、Touch (触屏)、XR (VR/AR 等)、All Devices (设备选择)作用:切换控制方案后,若该方案由多个设备配合控制,可进一步筛选对应设备,如切换键盘鼠标方案后可二次筛选 |
保存配置 | Auto-Save:自动保存配置 搜索栏:可搜索对应动作行为 |
编辑配置文件基本操作流程 | 1. 左上角添加控制方案(如手柄和鼠标键盘),在下面小列表分别选择设备 2. 在每个绑定设备中选择设备的控制方案 3. 左上角选择控制方案可筛选设备,选择后还可二次筛选设备 |
InputSystem中专门用于任意键按下的方案
InputSystem.onAnyButtonPress.CallOnce
InputSystem.onAnyButtonPress.CallOnce((control) =>
{
print("InputSystem中专门用于任意键按下的方案 路径" + control.path);
print("InputSystem中专门用于任意键按下的方案 名字" + control.name);
});
通过Json数据加载配置文件
string json = Resources.Load<TextAsset>("PlayerInputTest").text;
// 使用 InputActionAsset 类的静态方法 FromJson 解析 json 字符串,返回解析后的 InputActionAsset 对象,并将其存储在变量 asset 中
InputActionAsset asset = InputActionAsset.FromJson(json);
// 将解析后的 InputActionAsset 对象赋值给 input 对象的 actions 属性
input.actions = asset;
1.2.6.输入配置文件生成CSharp代码
类别 | 详情 | 示例 |
---|---|---|
课前准备 | 创建配置文件,在配置文件中创建两套行为 | 假设创建一个游戏相关的输入配置文件,一套行为是角色的战斗操作(如开火等),另一套行为是角色的移动和跳跃操作 |
根据配置文件生成C#代码 | 1. 选择 InputActions 文件,勾选 Generate C# Class 2. 在 Inspector 窗口设置生成路径(如 Assets/Scripts/GeneratedInputCode )、类名(如 CustomInputActions )、命名空间(如 MyGame.Input )3. 应用后生成代码,生成的代码根据 InputAction 配置文件解析 Json 生成类并提供一些方法 | 例如,在 Unity 项目中,已经创建好名为 MyInputActions.inputactions 的配置文件,选中它后在 Inspector 窗口勾选 Generate C# Class ,设置生成路径为 Assets/Scripts/InputCode ,类名为 GameInputActions ,命名空间为 GameProject.Input ,点击应用后,在指定路径下生成对应的 C# 代码文件 |
使用C#代码进行监听 | 声明对象 | GameInputActions input; 声明一个用于监听输入的配置文件对象(这里以 GameInputActions 为例,对应前面生成的类名) |
Start 方法 | 1. 创建生成的代码对象:input = new GameInputActions(); 实例化配置文件对象 2. 激活配置文件的输入: input.Enable(); 启用输入 3. 添加事件监听: input.Action1.Fire.performed += (context) => { print("鼠标点击 开火"); }; input.Action2.Space.performed += (context) => { print("空格按下 跳跃"); }; 假设 Action1 是战斗操作行为组,Fire 是其中的开火输入动作;Action2 是移动跳跃行为组,Space 是其中的跳跃输入动作 | |
Update 方法 | print("wasd移动" + input.Action1.Move.ReadValue<Vector2>()); 监听输入并打印相关信息 假设 Move 是 Action1 行为组中用于控制角色移动的输入动作,通过 ReadValue<Vector2> 获取移动的向量值并打印 |
1.3.PlayerInput
1.3.1.PlayerInput介绍
类别 | 详情 |
---|---|
PlayerInput 定义 | InputSystem 提供的用于接受玩家输入并处理自定义逻辑的组件 |
PlayerInput 工作原理 | 1. 配置输入文件(InputActions 文件)2. 通过 PlayerInput 关联配置文件,自动解析3. 关联响应函数,处理对应逻辑 |
PlayerInput 好处 | 1. 无需自己书写输入逻辑 2. 通过配置文件配置监听行为 3. 专注于输入事件触发后的逻辑处理 |
添加PlayerInput 组件 | 选择一个对象(一般为玩家对象),为其添加PlayerInput 组件 |
PlayerInput 参数 | Actions(行为) |
Default Scheme(默认控制方案) | |
Ui Input Module(UI输入模块) | |
Camera(摄像机) | |
Behavior(行为执行模式) | SendMessage :逻辑脚本挂载在与PlayerInput 同一对象上,通过SendMessage 通知执行函数BroadcastMessage :逻辑脚本可挂载在自身或子对象上,通过BroadcastMessage 通知执行函数Invoke UnityEvent Actions :在Inspector 窗口通过拖拽关联函数,响应函数参数类型为InputAction.CallbackContext ,可关联其他对象的脚本函数Invoke CSharp Events :通过获取PlayerInput 进行事件监听,可得到对应行为的值,如input.currentActionMap["Move"].ReadValue<Vector2>() |
SendMessage
示例:在自定义脚本中声明名为“On+行为名”的函数,无参数或参数类型为InputValue
,挂载到PlayerInput
依附对象上。代码如下:
public void OnMove(InputValue value)
{
print("Move");
print("Move" + value.Get<Vector2>());
}
public void OnFire(InputValue value)
{
print("Fire");
if (value.isPressed)
{
print("Fire按下");
}
}
BroadcastMessage
示例:基本规则同SendMessage
,自定义脚本还可挂载在子对象上
Invoke Unity Events
示例|在脚本中声明函数,如:
public void MyFire(InputAction.CallbackContext context)
{
print("开火1");
}
public void MyMove(InputAction.CallbackContext context)
{
print("移动1");
}
public void MyLook(InputAction.CallbackContext context)
{
print("Look1");
}
在Inspector
窗口通过拖拽关联函数|
Invoke C Sharp Events
示例|
(1). 获取PlayerInput
组件:
PlayerInput input = this.GetComponent<PlayerInput>();
(2). 添加委托函数:
input.onDeviceLost += OnDeviceLost;
input.onDeviceRegained += OnDeviceRegained;
input.onControlsChanged += OnControlsChanged;
input.onActionTriggered += OnActionTrigger;
(3). 处理事件:
public void OnActionTrigger(InputAction.CallbackContext context)
{
print("触发OnActionTrigger");
switch (context.action.name)
{
case "Fire":
if (context.phase == InputActionPhase.Performed)
print("开火");
break;
case "Look":
print("看向");
print(context.ReadValue<Vector2>());
break;
case "Move":
print("移动");
print(context.ReadValue<Vector2>());
break;
}
}
1.3.2.PlayerInput玩家输入管理组件
类别 | 详情 | 详情 |
---|---|---|
关键参数 | InputValue | 判断是否按下:inputValue.isPressed 获取 Vector2 类型值:inputValue.Get<Vector2>() |
InputAction.CallbackContext | 获取Vector2 类型值的x 和y 属性:callbackContext.ReadValue<Vector2>().x 、callbackContext.ReadValue<Vector2>().y 获取输入行为名字: callbackContext.action.name 获取输入控件名字: callbackContext.control.name 获取输入控件所属设备名字: callbackContext.control.device.name 获取输入阶段枚举值: callbackContext.phase 获取输入阶段字符串表示: callbackContext.phase.ToString() | |
PlayerInputManager 作用 | 用于管理本地多人输入的输入管理器,管理玩家加入和离开,如分屏游戏和双手柄游戏 | |
PlayerInputManager 组件参数 | Notification Behavior | 当玩家进入时,PlayerInputManager 通知关联对象的方式,与PlayerInput 工作方式相同 |
Join Behavior(玩家加入机制) | Join Players When Button Is Pressed :新设备加入或无玩家时按下任意键加入Join Players When Join Action Is Triggered :新设备加入时按下指定按键触发加入,一般选择此项Join Players Manually :手动加入玩家 | |
Player Prefab | 挂载PlayerInput 组件的游戏对象 | |
Joining Enabled By Default | 启用后,新加玩家按JoinBehavior 规则加入,默认勾选 | |
Limit Number Of Players | 启用后,可限制加入游戏的玩家数量,Max Player Count 为允许的最大玩家数 | |
Enable Split_Screen | 启用后,自动为每个对象分配屏幕区域用于多人分屏游戏Maintain Aspect Ratio :控制分屏区域纵横比与实际屏幕分辨率匹配Set Fixed Number :大于零时,始终将屏幕分割为固定数量矩形Screen Rectangle :用于分配玩家分屏的规范化屏幕矩形 |
PlayerInputManager
使用示例:
(1). 创建预制体方块,添加PlayerInput
组件和脚本,创建配置文件并关联到预制体的PlayerInput
组件,再关联到PlayerInputManger
的玩家预制体上(预制体需有PlayerInput
组件)
(2). 调整方块预制体对象输入行为为手动关联模式,关联脚本上的Move
函数,代码如下:
private Vector3 dir;
void Update()
{
this.transform.Translate(dir * 10 * Time.deltaTime);
}
public void Move(InputAction.CallbackContext context)
{
dir = context.ReadValue<Vector2>();
dir.z = dir.y;
dir.y = 0;
}
(3). 选择模式(如按A
键和手柄开始键创建新预制体),PlayerInputManager
自动处理输入控制
(4). 让方块预制体挂载摄像机,勾选分屏选项实现分屏效果
(5). 使用单例获取PlayerInputManager
并添加玩家加入和离开事件:
//获取PlayerInputManager
//PlayerInputManager.instance
//玩家加入时
PlayerInputManager.instance.onPlayerJoined += (playerInput) =>
{
print("创建了一个玩家");
};
//玩家离开时
PlayerInputManager.instance.onPlayerLeft += (playerInput) =>
{
print("离开了一个玩家");
};
1.4.UGUI配合使用
类别 | 详情 |
---|---|
InputSystem对UI的支持情况 | 不支持IMGUI(GUI),此限制仅对编辑器代码有效。若激活InputSystem,OnGUI 中输入判断内容不触发,让OnGUI 内容有效需选“Both”或只激活老输入系统InputManager ;支持UGUI,需用新输入系统的输入模块(Input System UI Input Module )处理相关输入 |
UGUI中新输入系统输入模块参数 | Move Repeat Delay |
Move Repeat Rate | 移动动作保持激活时,生成重复导航事件的间隔(秒),受帧速率限制,每帧不会有多个移动重复事件 |
XR Tracking Origin | 无明确详细说明 |
Deselect On Background CLick | 默认点击指针未击中游戏对象时清除当前选择,可能妨碍键盘和游戏板导航,设为false 可防止自动取消选择 |
Pointer Behavior | Single Mouse Or Pen BUt Multi Touch And Track:未分类为触摸或跟踪输入的按单个统一指针处理,跟踪和触摸输入按所有指针处理,触摸或跟踪设备输入时,鼠标和笔的单个统一指针会被删除 Single Unified Pointer:所有指针输入统一为一个指针,只有帧中最后一个输入生效 All Pointers As Is:UI输入模块不统一指针输入,每个设备输入都是独立指针,可能出现多个指针同时指向多个对象的情况 |
Actions Asset | 包含控制UI的所有操作的输入操作资产,默认引用DefaultInputActions 内置资产,可创建自定义资源并在此分配,编辑器会根据命名约定自动映射操作到UI输入 |
Point | 提供2D屏幕位置的动作,用于鼠标样式的UI交互,设置为传递操作类型和向量2值类型 |
Left Click | 映射到与UI交互的主光标按钮的操作,设置为传递操作类型和按钮值类型 |
Middle Click | 映射到与UI交互的中间光标按钮的操作,设置为传递操作类型和按钮值类型 |
Right Click | 映射到与UI交互的辅助光标按钮的操作,设置为传递操作类型和按钮值类型 |
Scroll Wheel | 提供手势输入以允许在UI中滚动的操作,设置为传递操作类型和向量2值类型 |
Move | 提供用于选择当前活动用户界面的二维矢量的操作,允许游戏板或箭头键样式的UI导航,设置为传递操作类型和向量2值类型 |
Submit | 与当前选择的UI接触或“单击”的操作,设置为按钮动作类型 |
Cancel | 退出与当前选定UI的任何交互的操作,设置为按钮动作类型 |
Tracked Position | 提供一个或多个空间跟踪设备(如XR hand控制器)的3D位置的动作,结合跟踪设备方向实现XR样式的UI交互,设置为传递操作类型和向量3值类型 |
Tracked Orientation | 传递表示一个或多个空间跟踪设备(如XR hand控制器)旋转的四元数的操作,结合跟踪设备位置实现XR样式的UI交互,设置为传递操作类型和四元数值类型 |
VR项目使用注意事项 | 在VR项目中用新输入系统配合UGUI,需在Canvas 对象上添加Tracked Device Raycaster 组件 |
多人游戏使用多套UI | 同一设备多人游戏,每人想用独立UI,需将EventSystem 中的EventSystem 组件替换为Multiplayer Event System 组件(先移除InputSystemUIInputModule 和EventSystem 组件再添加);可同时激活多个MultiplayerEventSystem ,每个玩家有自己的InputSystemUIInputModule 和MultiplayerEventSystem 组件及操作来驱动UI;若使用PlayerInput 组件,可设置其自动配置玩家的InputSystemUIInputModule ;MultilayerEventSystem 组件属性与事件系统中属性相同,还添加了playerRoot 属性,可设为包含此事件系统应处理的所有UI可选择项的游戏对象 |
On - Screen组件相关 | 可模拟UI和用户操作的交互,如On - Screen Button 用于按钮交互,On - Screen Stick 用于摇杆交互,关联之前输入配置文件设置好逻辑和关联设备的小球输入,如On - Screen Stick 关联手柄摇杆可像手柄摇杆一样控制小球移动,On - Screen Button 关联空格键可像按空格键一样控制小球跳跃 |
1.5.InputDebug输入调试器
类别 | 详情 |
---|---|
InputDebug 定义 | 即输入调试器,可通过输入调试窗口检测输入相关信息,用于在输入不按预期工作时排查问题 |
打开InputDebug 窗口的方式 | 1. 通过菜单栏:Window (窗口)-> Analysis (分析)-> Input Debugger (输入调试器)2. 通过 PlayerInput 组件:点击PlayerInput 组件上的Open Input Debugger |
InputDebug 窗口信息 - 未运行状态 | Options操作下拉框 |
Devices | |
Unsupported | |
Layouts | |
Controls | |
Abstract Devices | |
Specific Devices | |
Settings | |
Metrics | |
InputDebug 窗口信息 - 运行状态 | 双击设备可进行相关操作和查看更详细信息(文档中未明确具体内容,仅提及双击设备这一操作) |
2.VideoPlayer
2.1.视频剪辑设置
以下是将上述内容整理为表格的形式,方便你更清晰地了解视频剪辑设置的相关知识:
类别 | 参数 | 介绍 |
---|---|---|
设置参数 | sRGB | 是否开启 sRGB,sRGB 是通用色彩标准,避免不同设备出现色差,一般默认勾选 |
Transcode | 是否开启转码,开启后下方参数才能设置 | |
Dimensions | 控制源文件内容大小调整方式: 1. Original :保持原始大小2. Three Quarter Res :调整为原始宽高的四分之三3. Half Res :调整为原始宽高的一半4. Quarter Res :调整为原始宽高的四分之一5. Square(1024x1024) :调整为 1024x1024 正方形图像,宽高比可控6. Square(512x512) :调整为 512x512 正方形图像,宽高比可控7. Square(256x256) :调整为 256x256 正方形图像,宽高比可控8. Custom :调整为自定义分辨率,宽高比可控,可设置Width (生成图像的宽)、Height (生成图像的高)9. Aspect Ratio :调整图像大小时的宽高比,有No Scaling (添加黑色区域保留原始宽高比)、Stretch (拉伸原始内容填充目标分辨率) | |
Codec | 选择用于转码的解编码器: 1. Auto :为目标平台选择最合适的视频编解码器2. H264 :MPEG–4 高级视频编码 (AVC) 视频编解码器,受大多数平台硬件支持3. H265 :MPEG-H Part 2 或高效视频编码 (HEVC) 视频编解码器,受某些平台硬件支持4. VP8 :VP8 视频编解码器,受大多数平台软件支持,部分平台(如 Android 和 WebGL)硬件支持 | |
Bitrate Mode | 相对于所选编解码器的基线配置文件的低、中或高比特率 | |
Spatial Quality | 决定视频图像在转码过程中是否压缩大小: 1. Low Spatial Quality :转码时图像大小显著减小(通常为原始尺寸的四分之一),播放时扩展回原始大小,节省存储空间但播放时模糊度最大2. Medium Spatial Quality :转码时图像大小适度减小(通常为原始尺寸的一半),播放时扩展回原始大小,图像更清晰,存储空间有所减少3. High Spatial Quality :不调整大小,保持视频原始视觉清晰度 | |
Keep Alpha | 保留 Alpha 透明通道并在转码期间将其编码,仅对具有 Alpha 通道的源显示,Android 平台原生 VP8 不支持透明度,需启用转码 | |
Deinterlace(去交错设置) | 控制隔行扫描源在转码期间如何解除隔行扫描,优化动态画面清晰度: 1. Off :源文件没有隔行扫描,不进行隔行扫描2. Even :采用每个帧的偶数行,插入创建缺失内容,丢弃奇数行3. Odd :采用每个帧的奇数行,插入创建缺失内容,丢弃偶数行隔行扫描和逐行扫描区别: 隔行扫描:每一帧被分割为两场,包含奇数或偶数扫描行,交替显示,存在闪烁,人眼易疲劳 逐行扫描:每次显示整个扫描帧,画面更平滑,闪烁较小 | |
Filp Horizontally | 选中时,转码时将视频源文件内容沿水平轴翻转实现上下翻转 | |
Flip Vertically | 选中时,转码时将视频源文件内容沿垂直轴翻转实现左右翻转 | |
Import Audio | 只有存在音频轨道的视频才会出现该选项,勾选时,转码期间会导入音频轨道 |
2.2.VideoPlay视频播放器
2.2.1.VideoPlayer组件参数
参数分类 | 参数名称 | 参数说明 |
---|---|---|
视频源设置 | Source | 视频源类型,有 Video Clip 和 URL 两种选择 |
Video Clip | 可直接将视频剪辑拖入或选择视频剪辑进行关联 | |
URL | 选择视频的路径,可以是远程视频路径,可点击 Browse 选择,也能通过代码关联 | |
播放控制 | Play On Awake | 场景启动时自动播放视频,若想自行控制播放时机则取消勾选 |
Wait For First Frame | 勾选后,Unity 等待视频第一帧准备好显示;取消勾选可能丢弃前几帧以同步游戏时间 | |
Loop | 设置视频是否循环播放 | |
Skip On Drop | 决定是否允许视频播放器跳过帧以赶上当前时间 | |
Playback Speed | 播放速度的乘数,取值范围 0 - 10,1 为正常速度,2 表示两倍速播放 | |
渲染方式 | Render Mode | 包括 Camera Far Plane、Camera Near Plane、Render Texture、Material Override、API Only 等多种渲染模式 |
Camera Far Plane | 在摄像机的远平面上渲染视频 | |
Camera | 定义接受视频的摄像机,Alpha 可设置视频的全局透明度 | |
3D Layout | 包含不同的 3D 布局渲染方式 | |
Camera Near Plane | 在摄像机的近平面上渲染视频 | |
Render Texture | 将视频渲染到渲染纹理中,Target Texture 用于指定渲染图像的渲染纹理,分辨率最好和视频一致,可通过 UI 创建 image 关联视频纹理 | |
Material Override | 通过游戏对象渲染器的材质将视频渲染到游戏对象的选定纹理属性中,Renderer 用于指定渲染图像的渲染器,若为 None 则使用 Video Player 依附对象的渲染器 | |
API Only | 不预先设置渲染位置,通过代码使用 Video Player 中的 texture 属性设置视频渲染位置 | |
宽高比设置 | Aspect Ratio | 有 No Scaling、Fit Vertically、Fit Horizontally、Fit Inside、Fit Outside、Stretch 等多种宽高比设置方式 |
No Scaling | 不使用缩放 | |
Fit Vertically | 垂直适应目标矩形,必要时裁剪左右或留黑边保留原宽高比 | |
Fit Horizontally | 水平适应目标矩形,必要时裁剪上下或留黑边保留原宽高比 | |
Fit Inside | 对原视频缩放不裁剪,但可能留黑边 | |
Fit Outside | 对原视频缩放,可能裁剪但不留黑边 | |
Stretch | 水平和垂直方向均缩放以适应目标矩形,不保留源宽高比 | |
音频输出设置 | Audio Output Mode | 包括 None、Audio Source、Direct、API Only 等音频输出模式 |
None | 不播放音频 | |
Audio Source | 将音频发送给指定的音频源对象,允许 Unity 的音频处理,关联音频源后可通过其控制视频声音 | |
Direct | 直接绕过 Unity 音频处理,发送给音频输出硬件输出,如手机硬件 | |
Mute | 设置静音 | |
Volume | 调节音量 | |
API Only | 通过代码将音频样本发送到关联的 AudioSampleProvider 听诊器 | |
Track Enabled | 启用关联的音频轨道用于播放,必须在播放前设置,如“Track 0[en, 2 ch]”表示双声道音频轨道 |
2.2.2.VideoPlayer参数和方法
参数设置:
// 是否自动播放,设置为 false 表示不自动播放
videoPlayer.playOnAwake = false;
// 设置渲染模式为在摄像机的远平面上渲染
videoPlayer.renderMode = VideoRenderMode.CameraFarPlane;
// 设置目标渲染贴图为 renderTexture(需提前定义)
videoPlayer.targetTexture = renderTexture;
// 设置目标摄像机为名为 "Main Camera" 的摄像机
videoPlayer.targetCamera = GameObject.Find("Main Camera");
// 设置目标摄像机的透明度为 0.5
videoPlayer.targetCameraAlpha = 0.5f;
// 以 Over-Under3D 格式呈现视频
videoPlayer.targetCamera3DLayout = Video3DLayout.OverUnder3D;
// 设置视频源模式为使用视频剪辑
videoPlayer.source = VideoSource.VideoClip;
videoPlayer.clip = videoClip;
// 或者设置视频源模式为使用 URL 路径
// videoPlayer.source = VideoSource.Url;
// videoPlayer.url = Application.streamingAssetsPath + "/Video.mp4";
// 设置视频不循环播放
videoPlayer.isLooping = false;
视频状态输出:
// 输出视频总时长,单位为秒
print(videoPlayer.length);
// 输出当前视频播放的时长,单位为秒
print(videoPlayer.time);
// 输出视频的总帧数
print(videoPlayer.frameCount);
// 输出当前视频播放到的帧
print(videoPlayer.frame);
方法:
// 播放视频
videoPlayer.Play();
// 停止视频,再次播放时会从头开始
videoPlayer.Stop();
// 暂停视频播放
videoPlayer.Pause();
// 为视频准备数据,提前调用可避免播放时卡顿
videoPlayer.Prepare();
事件:
// 准备完成事件,当视频准备完成后触发,可用于避免播放卡顿
videoPlayer.prepareCompleted += (v) =>
{
print("准备完成");
isPrepareCompleted = true;
};
// 开始事件,当执行 videoPlayer.Play() 方法后调用
videoPlayer.started += (v) =>
{
print("当执行 player 播放方法后 会调用的事件");
};
// 结尾事件,当视频播放到结尾处时调用
videoPlayer.loopPointReached += (v) =>
{
print("视频播放到结尾处时会调用的事件");
};
2.3.全景视频
Unity 支持两种类型的全景视频:
- 等距圆柱投影布局:也被称为球面投影、简化圆柱投影、矩形投影或普通圆柱投影。这种布局的全景视频,其宽高比通常为 2:1(对应 360 度内容)或 1:1(对应 180 度内容)。
- 立方体贴图布局:由六个正方形纹理的集合构成。该布局的全景视频宽高比包括 1:6、3:4、4:3、6:1 等。可以通过视频分辨率的比值来判断该全景视频属于哪种布局类型。
在 Unity 中使用全景视频
(1). 导入等距圆柱投影布局的视频文件时,可以通过观察其分辨率是否为 2:1 来进行初步判定。
(2). 使用 Video Player 组件,将其渲染模式设置为以 Render Texture(渲染纹理)来播放视频。
(3). 设置接受渲染纹理的天空盒材质,具体操作为将天空盒材质的着色器设置为 Skybox>Panoramic。
(4). 配置场景,使其使用所设置的天空盒材质。
(5). 运行测试,尝试旋转摄像机的角度,查看全景视频的播放效果。
需要注意的是,为了获得更好的视觉效果,尽量使用较高分辨率的全景视频,如 4K 或 8K 分辨率。但对于一些老旧设备或者移动设备,由于性能限制,可能最多只能支持 2K 分辨率,具体情况需根据实际设备性能来确定。
** 使用全景视频时的注意事项**
(1). Render Texture(渲染纹理)方面:确保 Render Texture 的 Size(尺寸)与视频的尺寸保持一致,可以在视频预览窗口中选择 Source Info(源信息)来查看视频的分辨率。同时,将渲染纹理的 Depth Buffer(深度缓冲区)设置为 No depth buffer(无深度缓冲区)。
(2). 天空盒材质方面:
- 对于等距圆柱投影布局,在天空盒材质中将 Mapping(映射)设置为 Latitude Longitude Layout(经纬度布局),然后根据视频是 180 视图还是 360 视图,相应地选择 360 degree(360 度)或者 180 degree(180 度)。
- 对于立方体贴图布局,将 Mapping 设置为 6 Frames Layout(6 帧布局)。
- 如果视频是 VR 视频:
- 当视频内容分为左右双眼显示时,需要将天空盒材质的 3D Layout(3D 布局)设置为 Side by Side(并排)。
- 当左右侧内容在视频中呈上下分布时,3D Layout 应设置为 Over Under(上下)。
3.ScriptableObject
3.1.ScriptableObject数据文件的创建
注意:需要继承ScriptableObject类
(1)为类添加CreateAssetMenu通过菜单创建资源特性 [CreateAssetMenu(fileName = “默认文件名”, menuName = “在Asset/Create菜单中显示的名字”, order = 再Asset/Create菜单中的位置(多个时可以通过它来调整顺序))]
[CreateAssetMenu(fileName ="MrTangData", menuName ="ScriptableObject/我的数据", order = 0)]
public class MyData : ScriptableObject
{
}
(2)利用ScriptableObject的静态方法创建数据对象,然后将数据对象保存在工程目录下
// 调用ScriptableObject的静态方法CreateInstance<T>,创建一个继承自ScriptableObject的MyData类型的实例
// 这里的MyData是自定义的数据类,必须继承自ScriptableObject
MyData myDataAsset = ScriptableObject.CreateInstance<MyData>();
// 使用Unity编辑器的API AssetDatabase的CreateAsset方法,根据创建的实例myDataAsset
// 在指定路径"Assets/Unity进阶ScriptableObject教程/Lesson02_ScriptableObject数据文件的创建/MyDataTest.asset"创建一个数据资源文件
AssetDatabase.CreateAsset(myDataAsset, "Assets/Unity进阶ScriptableObject教程/Lesson02_ScriptableObject数据文件的创建/MyDataTest.asset");
// 调用AssetDatabase的SaveAssets方法,保存当前创建的所有资源文件到项目中
AssetDatabase.SaveAssets();
// 调用AssetDatabase的Refresh方法,刷新Unity编辑器的界面,使新创建的资源在编辑器中及时显示出来
AssetDatabase.Refresh();
3.2.ScriptableObject数据文件的使用
方法一:通过Inspector中的public变量进行关联
方法二:通过资源加载的信息关联
myData = Resources.Load<MyData>("MyDataTest");
3.3.ScriptableObject非持久数据和持久化
分类 | 详情 |
---|---|
回顾创建非持久化数据 | MyData myData = ScriptableObject.CreateInstance(); |
回顾数据持久化 | 数据在硬盘和内存之间交互,使用时从硬盘读取,改变后保存到硬盘,游戏退出或程序关闭后数据存储在硬盘实现持久化。已讲授的数据持久化方案包括PlayerPrefs、XML、Json、二进制等 |
利用Json结合ScriptableObject存储数据 | 示例代码如下:csharp<br>myData.PrintInfo();<br>myData.i = 9999;<br>myData.f = 6.6f;<br>myData.b = true;<br>//将数据对象序列化为json字符串:<br>string str = JsonUtility.ToJson(myData);<br>print(str);<br>//把数据序列化后的结果存入指定路径当中:<br>File.WriteAllText(Application.persistentDataPath + "/testJson.json", str);<br>print(Application.persistentDataPath);<br> |
利用Json结合ScriptableObject读取数据 | 示例代码如下:csharp<br>//从本地读取Json字符串:<br>str = File.ReadAllText(Application.persistentDataPath + "/testJson.json");<br>//根据json字符串反序列化出数据将内容覆盖到数据对象中:<br>JsonUtility.FromJsonOverwrite(str, myData);<br>// FromJsonOverwrite方法是将JSON数据覆盖到现有对象<br>// FromJson方法JSON数据转换为新的对象实例用一个新对象来接(就算用老对象来接 也是引用新的实例)<br>myData.PrintInfo();<br> |
总结 | ScriptableObject的数据在游戏发布运行过程中无法持久化,可借助PlayerPrefs、XML、Json、二进制等方式实现持久化,但不建议用ScriptableObject做数据持久化 |
3.4.ScriptableObject单例
实现单例模式化获取数据
实现单例模式化获取数据需要运用到面向对象、单例模式、泛型等知识。我们可以创建一个ScriptableObject
数据单例模式基类,这样一来,只要让子类继承这个基类,就可以直接获取到数据,而无需再使用public
关联或者资源动态加载的方式。
我们定义了一个名为SingleScriptableObject
的泛型类,它继承自ScriptableObject
。这个类的作用是实现单例模式的ScriptableObject
对象。在类中,定义了一个私有静态字段instance
,用于存储单例对象;还定义了一个公共静态属性Instance
,用于获取单例对象,该属性的类型为泛型参数T
。
在Instance
属性的get
访问器中,首先检查单例对象instance
是否为空。如果为空,就尝试从资源路径下加载对应的数据资源文件。按照约定,数据资源文件的路径为Resources/ScriptableObject/
,并且文件名与类名相同。如果没有找到对应的数据资源文件,为了保证程序的正常运行,会直接创建一个新的数据对象。最后,返回单例对象。具体代码如下:
public class SingleScriptableObject<T> : ScriptableObject where T : ScriptableObject
{
private static T instance;
public static T Instance
{
get
{
// 如果为空 首先应该去资源路径下加载 对应的 数据资源文件
if (instance == null)
{
// 我们定两个规则
// 1.所有的 数据资源文件都放在 Resources文件夹下的ScriptableObject中
// 2.需要复用的 唯一的数据资源文件名 我们定一个规则:和类名是一样的
instance = Resources.Load<T>("ScriptableObject/" + typeof(T).Name);
}
// 如果没有这个文件 为了安全起见 我们可以在这直接创建一个数据
if (instance == null)
{
instance = CreateInstance<T>();
}
// 甚至可以在这里 从json当中读取数据,但是我不建议用ScriptableObject来做数据持久化
return instance;
}
}
}
例如,让RoleInfo
类继承SingleScriptableObject
:
public class RoleInfo : SingleScriptableObject<RoleInfo>
或者创建TestData
类继承SingleScriptableObject
:
[CreateAssetMenu]
public class TestData : SingleScriptableObject<TestData>
{
public int i;
public bool b;
}
这样,就可以直接使用Instance
单例来获取数据文件了。无论Resource/ScriptableObject
路径下有没有对应的数据文件都可以正常获取。如果没有,程序会动态生成默认的数据。使用示例如下:
print(RoleInfo.Instance.roleList[0].id);
print(RoleInfo.Instance.roleList[1].tips);
print(TestData.Instance.i);
print(TestData.Instance.b);
4.TextMeshPro
4.1.TextMeshPro UI
4.1.1.TextMeshPro UI组件参数
分类 | 具体项目 | 详细说明 |
---|---|---|
Enable RTL Editor | 开启后文本从右向左显示,下方出现RTL Text Input框,可查看并编辑反转文本 | |
Text Style | H1、H2、H3:标题级别,数字越大级别越低 C1、C2、C3:颜色级别,区分文本颜色 Quote:引用文本样式 Link:超链接文本格式样式 Title:标题样式 Normal:普通正文文本样式 | |
字体相关 | Font Asset:可选择默认字体资源,TMP字体支持自定义 Material Preset:TMP字体显示基于材质球,切换材质球改变渲染效果(因Shader着色器不同),可调整材质球参数(如边缘线) Font Style:B:加粗(Bold);I:斜体(Italic);U:下划线(Underline);S:删除线(Strikethrough);ab:小写文本(Small Caps Lowercase);AB:大写文本(All Caps);SC:大写文本,按实际输入字母大小显示(Small Caps) Auto Size:勾选后有更多设置选项,消耗大少用。Auto Size Options:Min:最小字体大小(Minimum Size);Max:最大字体大小(Maximum Size);WD%:水平挤压字符(Width Percentage);Line:减少行间距(负数)(Line Spacing Reduction,negative value) | |
颜色 | 顶点颜色 | 与材质和纹理颜色相乘,决定字体最终颜色 |
颜色渐变 | 勾选后有新参数: Color Preset:颜色预设(Color Preset) Color Mode:Single:与顶点颜色叠加(Overlay with Vertex Color);Horizontal Gradient:双色水平渐变(Two-Color Horizontal Gradient);Vertical Gradient:双色垂直渐变(Two-Color Vertical Gradient);Four Corners Gradient:四色四角渐变(Four-Color Four-Corners Gradient) Colors:依颜色模式设置多个颜色值 | |
Override Tags | 启用可忽略富文本标记对颜色的更改,通常不勾选 | |
间距 | 字符间距 (Character) | 控制每个字符间的间距 |
单词间距 (Word) | 控制每个单词间的间距 | |
行间距 (Line) | 控制行与行间的间距,适用于自动换行文本 | |
段落间距 (Paragraph) | 控制段落间的间距,段落由显式换行符定义 | |
对齐 | 水平对齐 | 左对齐:文本靠左对齐(Left Align) 居中对齐:文本居中对齐(Center Align) 右对齐:文本靠右对齐(Right Align) 拉伸左对齐:增加间距填满行,最后一行不拉伸(Justify Left,last line not justified) 拉伸齐平:类似拉伸左对齐,最后一行也拉伸(Justify Full) 网格居中:按网格居中文本,效果更细致(Mesh Center,more delicate effect) |
垂直对齐 | 顶部对齐:文本靠顶部对齐(Top Align) 中部对齐:文本垂直居中对齐(Middle Align Vertically) 底部对齐:文本靠底部对齐(Bottom Align) 基线对齐:第一行基线与显示区域中间对齐,适用于单行文本(Baseline Align,suitable for single-line text) 中线对齐:类似中部对齐,依文本网格边界垂直放置,适合狭小空间(Middle Line Align,placed vertically according to text mesh boundary,suitable for narrow spaces) 卡普赖恩对齐:第一行中间与显示区域中间对齐(Cap Height Align,align the middle of the first line with the middle of the display area) | |
包裹与溢出 | Wrapping | Disabled:文本不自动换行,溢出显示(受溢出选项影响)(Text does not wrap automatically, and overflows as shown (affected by the overflow option)) Enabled:控件大小变化时文本自动换行(Text wraps automatically when the control size changes) |
Overflow | Overflow:文本溢出到显示区域外,若启用包裹会自动换行(Text overflows outside the display area. If wrapping is enabled, the text will wrap automatically) Ellipsis:超出部分用省略号代替(Replace the overflowing part with an ellipsis) Masking:类似Overflow,隐藏显示区域外内容(Similar to Overflow, hide the content outside the display area) Truncate:超出内容直接截断不显示(Truncate the overflowing content and do not display it) Scroll Rect:仅用于旧版TextMesh Pro项目兼容,新项目建议用遮罩模式(Only used for compatibility with legacy TextMesh Pro projects. It is recommended to use the masking mode for new projects) Page:文本切分为多个页面,可选择显示具体页面内容(Divide the text into multiple pages, and you can select the specific page content to display) Linked:文本扩展到指定TextMesh Pro游戏对象,当前对象溢出内容在关联对象显示(Extend the text to the specified TextMesh Pro game object, and the overflowing content of the current object will be displayed in the associated object) | |
UV映射 | Horizontal Mapping | Character:在每个文字上水平拉伸纹理(Stretch the texture horizontally on each character) Line:在每条线宽度上水平拉伸纹理(Stretch the texture horizontally across the entire width of each line) Paragraph:在整个文本中水平拉伸纹理(Stretch the texture horizontally across the entire text) Match Aspect:水平缩放纹理,保持纵横比不变(Scale the texture horizontally while maintaining the aspect ratio) |
Vertical Mapping | Character:在每个文字上垂直拉伸纹理(Stretch the texture vertically on each character) Line:在每条线高度上垂直拉伸纹理(Stretch the texture vertically across the entire height of each line) Paragraph:在整个文本中垂直拉伸纹理(Stretch the texture vertically across the entire text) Match Aspect:垂直缩放纹理,保持纵横比不变(Scale the texture vertically while maintaining the aspect ratio) | |
Line Offset | 选择“Line”“Paragraph”或“Match Aspect”模式时,控制纹理偏移位置(Control the texture offset position when the “Line”, “Paragraph”, or “Match Aspect” mode is selected) | |
额外设置 | 边缘设置 (Margins) | 设置文本和文本容器间的间距,可用负值使文本超出边框,可在Scene窗口操作黄色边框调整 |
几何排序 (Geometry Sorting) | Normal:按显示顺序排序,重叠时靠近摄像机的在前面(Sort according to the display order. When quadrilaterals overlap, the ones closer to the camera are in the front) Reverse:按相反顺序绘制四边形,重叠时远离摄像机的在前面(Draw quadrilaterals in the opposite order. When they overlap, the ones farther from the camera are in the front) | |
是否静态缩放 (Is Scale Static) | 告诉TMP文本系统文本无缩放变化,TMP跳过缩放计算,减少CPU和GPU负担,适用于缩放比例固定的文本对象 | |
富文本 (Rich Text) | 控制是否开启富文本,默认开启,开启后可识别富文本关键字 | |
射线检测目标 (Raycast Target) | 决定文本是否响应点击、触摸等事件,关闭时触摸和点击“穿透”,需响应则勾选 | |
遮罩裁剪 (Maskable) | 决定文本是否被Mask组件裁剪,勾选时被裁剪,取消勾选时不被裁剪 | |
转义字符解析 (Parse Escape Characters) | 决定文本是否解析转义字符,开启时解析,关闭时无效 | |
可见下降 (Visible Descender) | 用脚本缓慢显示文本时启用,可显示底部文本,显示新行时向上移动,需将垂直对齐改为Bottom | |
精灵资源 (Sprite Asset) | 允许在文本中嵌入2D精灵图片,处理图文混排,如嵌入表情符号 | |
样式表资源 (Style Sheet Asset) | 管理和应用文本样式,TMP_Style Sheet文件定义多种样式,可在多个文本组件重复使用,确保样式一致 | |
自动字符间距调整 (Kerning) | 自动调整字符间距,提高文本可读性和美观性 | |
额外填充 (Extra Padding) | 为文本边界添加额外填充,避免文本与边界过近,提升视觉效果 |
4.1.2.TextMeshPro UI参数和方法```
TextMeshPro UI 组件常用属性
属性 | 说明 | 示例代码 |
---|---|---|
文本内容 (text) | 用于设置或获取文本显示的内容 | textMeshProUGUI.text = "123123adfasdklf545454564654654646454564654132156465424"; |
字体 (font) | 可获取或设置所使用的字体 | textMeshProUGUI.font = ...; // 获取或设置字体 |
字体大小 (fontSize) | 设置字体的大小 | textMeshProUGUI.fontSize = 10; |
颜色 (color) | 设置文本的颜色 | textMeshProUGUI.color = Color.black; |
对齐方式 (alignment) | 设置文本的对齐方式 | textMeshProUGUI.alignment = TextAlignmentOptions.Center; |
行间距 (lineSpacing) | 设置文本行与行之间的间距 | textMeshProUGUI.lineSpacing = 50; |
是否启用富文本 (richText) | 决定是否启用富文本格式 | textMeshProUGUI.richText = false; |
TextMeshPro UI 组件常用方法
方法 | 说明 | 示例代码 |
---|---|---|
SetText | 设置文本内容,支持富文本格式 | textMeshProUGUI.SetText("<color=blue>Hello, World!</color>"); |
Rebuild | 强制重新构建文本网格,在文本内容或样式更改后调用 | textMeshProUGUI.Rebuild(UnityEngine.UI.CanvasUpdate.Prelayout); |
ForceMeshUpdate | 在运行时动态更改文本时,强制更新文本网格 | textMeshProUGUI.ForceMeshUpdate(); |
Length | 获取文本中字符的数量 | print(textMeshProUGUI.text.Length); |
CanvasUpdate
枚举
Prelayout
:布局前调用Layout
:布局时调用PostLayout
:布局后调用PreRender
:渲染前调用LatePreRender
:渲染后调用MaxUpdateValue
:最后调用
** UI 事件监听**
若要为 TMP UI 添加交互事件,可使用 UGUI 中的 EventTrigger
组件。
4.2. 3D 文本和 UI 文本区别:
分类 | 3D 文本(TextMeshPro) | UI 文本(TextMeshProUGUI) |
---|---|---|
使用的组件 | 使用 TextMeshPro 组件 | 使用 TextMeshProUGUI 组件 |
用途 | 主要用于在 3D 场景中显示文字 | 主要用于在 UI 中显示文字,具备与 UI 相关的一些属性 |
渲染方式 | 直接渲染在场景上 | 通过 UGUI 的 Canvas 系统渲染 |
交互方式 | 通常通过添加碰撞器进行碰撞检测来判断交互 | 一般利用 UI 系统的交互规则,比如 EventTrigger |
如何选择 | 如果文本需要与 3D 场景交互,或者需要在 3D 场景中显示,选择 3D 文本 TextMeshPro ,将其视为 3D 物体进行处理 | 如果文本需要在 UI 系统中使用,选择 TextMeshProUGUI ,将其视为 UI 组件处理 |
参数相关 | 3D 文本的参数设置与 UI 文本的相关参数几乎完全一致 | UI 文本有与 UI 系统相关的一些属性设置 |
脚本控制 | 示例代码:using TMPro;using UnityEngine;public class Lesson09_3D 文本 : MonoBehaviour{ public TextMeshProUGUI textMeshProUGUI; // UI 文本组件<br> public TextMeshPro textMeshPro; // 3D 文本组件} | 与 3D 文本在脚本控制上,组件名称不同,其他部分属性和方法几乎一致 |
4.3.字体资源
4.3.1.字体资源-基本信息设置
分类 | 设置项 | 详细说明 |
---|---|---|
更新纹理图集 | 操作按钮 | 点击“更新纹理图集”,打开字体资源创建器新窗口,用于配置字体的图集纹理信息和生成静态字体资源,可将 Unity 字体资源转换为 TMP 字体资源,生成后若不再用源字体资源重新生成 TMP 字体,可删除源字体资源 |
基本信息设置 | Source Font File | 选择用于生成 TMP 字体资源的字体 |
Sampling Point Size | 设置用于生成字体纹理的字体大小(以磅为单位),有“Auto Sizing”(使用尽可能大的大小,常用设置)和“Custom Size”(自定义大小)两种方式 | |
Padding | 指定字体纹理中字符之间的间距(以像素为单位),填充越大,过渡越平滑 | |
Packing Method | Fast:字符打包速度快,但字体的大小可能更小,测试字体时可使用 Optimum:尽可能合理利用纹理中的空间,保持字符最大可能的字体大小,正式确定字体时使用 | |
Atlas Resolution | 根据字符集选择合适的分辨率,如只有 ASCII 字符,用 512x512 即可;中文字体时,需要更大更多的图集(比如 1024x1024) | |
Character Set | ASCII:标准 ASCII 字符集(字母,数字,标点符号) Extended ASCII:拓展 ASCII 字符集(增加了许多特殊字符和符号) ASCII Lowercase:仅包含小写字母字符(a~z) ASCII Uppercase:仅包含大写字母字符(A-Z) Numbers + Symbols:包含数字(0-9)和常见的符号(如 !, @, #, $, % 等) Custom Range:允许用户定义一个自定义字符范围,用户可以指定要包含的 Unicode 范围 Unicode Range(Hex):允许用户输入 Unicode 范围的十六进制值 Custom Characters:用户可以手动输入要包含的具体字符,可以是任何字符(如字母、符号等) Characters from File:从文本文件中读取字符,允许用户根据文件内容自动生成字符集,适合大量字符的处理 | |
Select Font Asset | 选择对应的字体资源 | |
Character Sequence | 当选择需要自己输入字体的相关模式时,会出现 | |
Render Mode | SMOOTH_HINTED:抗锯齿位图,字符像素和纹理像素对齐,以获得更清晰的结果,通常用于小字体或需要精确对齐的情况 SMOOTH:采用抗锯齿效果,提供平滑的边缘,适合大多数情况下的文本显示 COLOR_HINTED:基于颜色的抗锯齿效果,强调颜色的呈现,适合需要突出颜色的文本 COLOR:不使用抗锯齿,直接渲染文本的颜色,适合在高对比度或需要清晰边缘的场景中使用 RASTER_HINTED:位图渲染,通常用于较小字体,能够提供较高的清晰度 RASTER:位图渲染,不进行抗锯齿处理,提供快速渲染,但在边缘可能出现锯齿现象 SDF:使用带符号的距离场技术渲染,能够在缩放时保持清晰度 SDF8:使用 8 位 SDF 渲染,支持更小的纹理,适合资源受限的环境 SDF16:使用 16 位 SDF 渲染,提供更高的清晰度和更细腻的边缘 SDF32:使用 32 位 SDF 渲染,具有最高的细节和清晰度 SDFAA_HINTED:使用抗锯齿的 SDF 渲染,提供平滑的边缘和清晰的字符显示 SDFAA:使用 SDF 渲染,但不进行抗锯齿处理,快速渲染 | |
Get Kerning Pairs | 用于在字体资源中获取字偶间距调整(Kerning)对 | |
Generate Font Atlas | 生成字体图集 | |
Save | 保存图集 | |
Save as… | 另存为 | |
字体属性设置 | Family Name | 字体名称,无法手动修改,创建字体资源时默认设置 |
Style Name | 样式名称,无法手动修改,创建字体资源时默认设置 | |
Point Size | 字体大小(以磅 Point,缩写 pt 为单位),1 磅等于 1/72 英寸(约 0.353 毫米),在字体设计中,磅数用来表示字体的高度 | |
Scale | 对字体进行缩放,1 为原始大小,不缩放 | |
Line Height | 表示每行文本的高度,通常是基于最大字形的高度计算的,决定了两行文本之间的距离 | |
Ascent Line | 字形中最高的点到基线的垂直距离,表示字母中最高部分(大写字母或某字符的上部)的位置 | |
Cap Line | 表示所有大写字母的顶部所处的水平线,通常略低于上升线 | |
Mean Line | 表示小写字母的顶部所处的水平线,表示小写字母的标准高度 | |
BaseLine | 所有字母字符所处的水平线,大多数字符都在这条线的上方 | |
Descent Line | 字形中最低的点到基线的垂直距离,表示字母中最低部分的水平线 | |
Underline Offset | 下划线相对基线的位置 | |
Underline Thickness | 控制下划线的粗细 | |
Strikethrough Offset | 控制删除线相对于基线的位置 | |
Superscript Offset | 使上标文本相对基线偏移 | |
Superscript Size | 相对于正常字体大小缩放上标文本 | |
Subscript Offset | 使下标文本相对基线偏移 | |
Subscript Size | 相对于正常字体大小缩放下标文本 | |
Tab Width | 指定 TAB 字符的宽度 |
4.3.2.字体资源-生成设置和图集纹理
分类 | 设置项 | 详细说明 |
---|---|---|
基本设置 | Source Font File | 用于指定字体资源所使用的字体文件 |
Atlas Population Mode | 纹理图集生成方式,有以下两种模式: Static(静态模式):字体集在创建时需要一个固定的纹理图集,适用于字符已知且不需要动态变化的情况,如仅有少量英文字符时。 Dynamic(动态模式):字体纹理图集会在运行时根据需要动态生成,能够显示更多字符,适合中文项目或多语言项目 | |
Atlas Render Mode | 字体渲染模式,具体如下: SMOOTH_HINTED:抗锯齿位图,字符像素和纹理像素对齐,适合小字体或精确对齐的场景。 SMOOTH:提供平滑边缘,适用于大多数文本显示,兼顾清晰度和性能。 COLOR_HINTED:基于颜色的抗锯齿,突出颜色效果。 COLOR:不使用抗锯齿,适用于高对比度或需要清晰边缘的场景。 RASTER_HINTED:位图渲染,适合较小字体,但放大时可能模糊。 RASTER:快速渲染模式,但边缘可能出现锯齿。 SDF:带符号距离场技术,支持缩放时保持清晰。 SDF8:8 位 SDF 渲染,适用于资源受限环境。 SDF16:16 位 SDF 渲染,提供更高清晰度。 SDF32:32 位 SDF 渲染,适合需要极高质量的文本。 SDFAA_HINTED:抗锯齿的 SDF 渲染,提供平滑边缘和清晰字符显示。 SDFAA:SDF 渲染但无抗锯齿,快速渲染但可能出现锯齿 | |
Sampling Point Size | 设置生成字体纹理时的字体大小,单位为磅,有以下两种设置方式: Auto Sizing:使用尽可能大的字体大小(推荐)。 Custom Size:自定义字体大小 | |
Padding | 指定字体纹理中字符之间的间距,单位为像素,较大的填充值可以提供更平滑的过渡效果 | |
Atlas Width | 设置字体纹理图集的宽度 | |
Atlas Height | 设置字体纹理图集的高度 | |
Multi Atlas Textures | 是否采用多图纹理,允许在字体资源中生成多个纹理图集(Atlas),而不仅仅是一个。这样可以更灵活地管理不同字符集或不同字体样式,提高性能和内存使用效率,尤其是在需要渲染大量不同字符的情况下建议使用 | |
Clear Dynamic Data On Build | 在构建时清除动态生成的数据。若选择了动态字体模式,构建时会移除不再需要的动态字符数据,以节省内存,减少最终构建包的大小,确保只包含必要的字符数据 | |
Font Atlas | 生成字符资源时创建的字体纹理图集 | |
Font Material | 生成字体资源时创建的字体材质 |
4.3.3.字体资源-字体粗细
分类 | 设置项 | 详细说明 |
---|---|---|
字体类型 | Regular Typeface | 常规字体 |
Italic Typeface | 斜体字体 | |
字体粗细等级 | 100 - thin | 细 |
200 - Extra - Light | 超轻 | |
300 - Light | 轻 | |
400 - Regular | 常规(仅限斜体) | |
500 - Medium | 中 | |
600 - Semi - Bold | 半粗 | |
700 - Bold | 粗体 | |
800 - Heavy | 粗 | |
900 - Black | 黑体 | |
默认粗细 | Normal Weight | 没有字体资源用时使用的常规字体粗细 |
Bold Weight | 没有字体资源用时使用的粗体字体粗细 | |
间距设置 | Spacing Offset | 使用普通文本样式时,在字符之间的间隙偏移 |
Bold Spacing | 没有指定粗体资源时,粗体文本字符之间的间距偏移 | |
斜体样式 | Italic Style | 400 - Regular > Italic Style 变体指定字体资源没有设置时,TMP将使用常规样式字体资源中的字符倾斜该字段中的量来达到斜体效果 |
制表符设置 | Tab Multiple | 该值乘以字体空格符的宽度,用来表示制表符的大小 |
4.3.4.字体资源-其他设置
分类 | 设置项 | 详细说明 |
---|---|---|
备用字体资源 | Fallback Font Assets | 每个字体资源包含字符数量有限,当使用当前字体资源不包含的字符时,TMP 会搜索回退字体列表,找到包含该字符的字体资源用于呈现字符 |
Fallback List | 列出所有备用字体资产,主字体缺少某些字符时,系统按顺序尝试使用这些备用字体查找。可创建字体变体关联该列表,在字体变体中做特殊字符添加等处理 | |
字符表 | Character Table - Character Search | 用于字符查找 |
字形表 | Glyph Table - Glyph Search | 用于字形搜索 |
X、Y、W、H | 字符在纹理中对应的位置范围 | |
W、H | 字形的宽高 | |
BX、BY | 相对基线的左上角位置 | |
AD | 和下一个字符间隔的宽 | |
Scale | 缩放大小 | |
Atlas Index | 图集索引,在开启多图集时,表示在第几个图集中 | |
字形调整表 | Glyph Adjustment Table | 控制特定字符对之间的间距 |
Adjustment Pair Search | 用于调整对搜索 | |
Char 左和右 | 想要查找的字符 | |
ID 左和右 | 唯一标识符,一般显示左右字符的 ASCII 十进制编码 | |
OX 左和右 | 字符原点坐标 X | |
OY 左和右 | 字符原点坐标 Y | |
AX 左和右 | 字符的宽度 | |
Add New Glyph Adjustment Record | 添加新的字形调整记录 |
4.4.富文本标签
标签 | 详情 |
---|---|
文本加粗 | <b></b> |
文本斜体 | <i></i> |
加下划线 | <u></u> |
改变大小 | <size=数值></size> |
改变颜色 | <color=#RGBA 16 进制></color> |
对齐方式 | <align=left、center、right、justified、flush></align> |
背景高亮 | <mark=#RGBA 16 进制></mark> |
透明度 | <alpha=#A 16 进制> |
全部大写 | <allcaps></allcaps> |
改字体和材质(可选) | <font="字体名" material="材质名"></font> |
加上标 (平方) | <sup></sup> |
加下标 (化学式) | <sub></sub> |
超链接 | <link="链接"></link> |
文本加粗示例 | <b>这是文本加粗示例。</b> |
文本斜体示例 | <i>这是文本斜体示例。</i> |
加下划线示例 | <u>这是加下划线示例。</u> |
改变大小示例 | <size=30>这是改变大小示例。</size> |
改变颜色示例 | <color=#00FF00>这是改变颜色示例。</color> |
左对齐示例 | <align=left>这是左对齐示例。</align> |
背景高亮示例 | <mark=#FFFF00>这是背景高亮示例。</mark> |
透明度示例 | <alpha=#80>这是透明度示例。</alpha> |
全部大写示例 | <allcaps>这是全部大写示例。</allcaps> |
改字体和材质示例 | <font="LiberationSans SDF" material="LiberationSans SDF - Outline">123 这是改字体和材质示例。</font> |
加上标示例 | 正常<sup>这是加上标示例。</sup> |
加下标示例 | 正常<sub>这是加下标示例。</sub> |
超链接示例 | <link="https://www.example.com">这是超链接示例。</link> |
4.5.样式表
分类 | 详情 |
---|---|
定义 | 样式表是 TMP 提供的与富文本标签配合使用的功能,可自定义文本样式,在富文本中用<style="样式表名"></style> 标签包裹文字应用样式,本质是对富文本标签的复用,能避免重复书写冗余的富文本样式编码 |
修改和创建 | 修改默认样式表 |
创建样式表 | |
配置参数 | Name |
HashCode | |
Opening Tags | |
Closing Tags | |
Up、Down | |
+、- | |
Previous、Next | |
样式对应 | |
设置关联 | 每一个 TMP 控件中的额外设置中,都可关联对应的样式表资源,若未设置,则使用默认样式表 |
4.6.图文混排
分类 | 操作 | 详情 |
---|---|---|
定义 | 精灵图片资源是与富文本标签配合使用的资源,可在 TMP 文本中显示图片,实现图文混排,创建并配置好后,利用富文本标签在文本中展示图片 | |
创建 | 创建图集 | 根据需求建立图集纹理,Texture Type 设为 Sprite,Sprite Mode 设为 Multiple,需导入 2D Sprite 包,在 Sprite Editor 中将图集中图片划分为单独的 Sprite |
创建精灵图片资源 | 准备好图集文件后,在 Project 窗口选中图集右键 → Text Mesh Pro → Sprite Asset 创建。创建后需设置: 1. 图片名称。 2. 图片位置和宽度相关参数,配合全局偏移和缩放参数设置。 关键参数: BX、BY:相对于基线的原点的左上角。 AD:放置下一个内容时向右前进的位置 | |
使用 | 默认资源获取图片 | 使用以下标签格式: 1. <sprite index=图片ID color=#RGBA的16进制(可选)> 2. <sprite name="图片名" color=#RGBA的16进制(可选)> 3. <sprite=图片ID color=#RGBA的16进制(可选)> |
指定资源获取图片 | 使用以下标签格式: 1. <sprite="资源名" index=图片ID color=#RGBA的16进制(可选)> 2. <sprite="资源名" name="图片名" color=#RGBA的16进制(可选)> | |
关联使用 | 可将精灵图片资源直接关联到对应的 TMP 文本控件中使用,若不关联,则使用默认资源 | |
示例演示 | <sprite index=0 color=#FF0000> <sprite name="EmojiOne_0" color=#00FF00> <sprite=0 color=#0000FF> |
4.7.项目设置TextMeshPro基本设置
分类 | 设置项 | 详细说明 |
---|---|---|
默认字体设置 | Default Font Asset | 存储默认字体设置相关信息 |
Path | 字体资源的存储位置 | |
备用字体资源 | Fallback Font Assets | 设置备用字体资源,用于当前字体资源无法满足需求的场景 |
Fallback Material Settings | 备用材质设置 | |
Match Material Presets | 启用后,备用字体中的字形与主字体的样式匹配,使主字体和后备字体看起来更接近 | |
动态字体系统设置 | Dynamic Font System Setting | 配置动态字体系统相关选项 |
Get Font Features at Runtime | 运行时获取字体功能 | |
Missing Character Unicode | 当找不到字符时使用的替代字符,默认值为 0,显示为一个正方形轮廓 | |
Disable warnings | 启用后可避免 Unity 为每个缺失字形记录的警告 | |
文本容器默认设置 | Text Container Default Setting | 设置文本容器的默认行为和选项 |
TextMeshPro | 3D 文本默认大小 | |
TextMeshPro UI | UI 文本默认大小 | |
Enable Raycast Target | 是否默认为文本对象启用射线检测 | |
Auto Size Text Container | 启用后会自动调整文本容器的大小 | |
Is Object Scale Static | 是否为静态缩放 | |
文本组件默认设置 | Text Component Default Setting | 设置文本组件相关的默认行为 |
Default Font Size | 默认字体大小 | |
Text Auto Size Ratios | 文本自动调整大小比例 | |
Word Wrapping | 是否启用自动换行 | |
Kerning | 是否启用字偶间距调整 | |
Extra Padding | 是否额外进行填充,可降低字符在精灵边界处被截断的几率 | |
Tint All Sprites | 为所有精灵图片着色 | |
Parse Escape Sequence | 是否解析转义字符 | |
默认精灵图片资源 | Default Sprite Asset | 设置文本精灵图片相关选项 |
Missing Sprite Unicode | 精灵缺失时采用的替代符,默认为方形轮廓 | |
IOS Emoji Support | 是否支持 IOS 表情符号 | |
Path | 精灵图片资源存储路径 | |
默认样式表 | Default Style Sheet | 设置默认样式表的路径 |
Path | 样式表资源存储路径 | |
默认颜色渐变预设 | Color Gradient Presets | 设置默认颜色渐变选项 |
Path | 颜色渐变预设存储路径 | |
亚洲语言换行规则 | Line Breaking for Asian Languages | 用于处理亚洲语言的换行规则,设置亚洲语言换行相关的行为 |
Leading Characters | 前导符号,一般不允许出现在行首,遇到这些字符触发自动换行时,字符会显示在尾部 | |
Following Characters | 尾随符号,一般不允许出现在行尾,如果这些符号出现在行尾触发自动换行时,会将这些符号移动到下一行 | |
韩语相关设置 | Korean Language Options | 用于设置与韩语换行规则相关的选项 |
Use Modern Line Breaking | 使用现代换行,启用后将采用更符合韩语规则的换行方式 |
4.8.SDF材质球
分类 | 设置项 | 详细说明 |
---|---|---|
SDF 含义 | 有符号(Signed) | 距离可以为正或负,正表示点位于边界外部,负表示点位于边界内部 |
距离(Distance) | 每个像素点到字符边缘的距离 | |
场(Field) | 整个字体或图形周围的距离值的分布 | |
技术本质 | 在 Shader 中利用 SDF 算法渲染文字,生成的字体纹理基于每个像素到字体边缘的距离值,存储在纹理灰度通道,渲染时着色器根据距离值计算字体边缘,呈现平滑字符轮廓 | |
在 TMP 中的作用 | 用于生成和渲染文本,使字体在任意大小或距离下保持清晰和锐利效果 | |
SDF 材质球含义 | 本质 | 使用了 SDF Shader 的材质球 |
效果 | 利用该 Shader 渲染的字体效果更好 | |
可配置性 | Shader 提供许多可配置参数,调整参数可实现复杂美术表现效果 | |
SDF 材质球主要内容 | 基础表面设置(Face) | Color:文本表面颜色,与 TMP 组件中设置颜色相乘叠加 Texture:为文本添加贴图 Tiling:平铺(缩放) Offset:偏移 Speed:移动速度(可实现滚动效果,配合 UV 配置) Softness:边缘柔和度,使文字边缘模糊 Dilate:拓展,类似改变字体粗细 |
边缘线设置(Outline) | Color:边缘线颜色 Texture:边缘线纹理,与轮廓颜色相乘叠加 Thickness:轮廓粗细,值越大越粗 | |
阴影(底层)设置(Underlay) | Underlay Type: None:无阴影 Normal:标准底图样式 Inner:反转底图,用原始文本遮罩它 Color:底图阴影颜色 Offset X:X 轴偏移 Offset Y:Y 轴偏移 Dilate:拓展,改变粗细 Softness:边缘柔和度,使阴影边界模糊 | |
照明设置(Lighting) - 斜面设置(Bevel) | Type 类型: Outer Bevel:外斜面,字体有倾斜侧面的凸起效果 Inner Bevel:内斜面,字体轮廓向内凹陷 Amount:陡峭程度 Offset:位置偏移 Width:斜面大小 Roundness:使斜面更平滑 Clamp:限制斜面最大高度 | |
照明设置(Lighting) - 本地照明设置(Local Lighting) | Light Angle:光照角度 Specular Color:镜面反射颜色 Specular Power:镜面反射强度 Reflectivity Power:反射强度 Diffuse Shadow:漫反射阴影 Amblent Shadow:环境阴影 | |
照明设置(Lighting) - 凹凸贴图设置(Bump Map) | Texture:凹凸贴图 Face:凹凸影响程度 Outline:凹凸贴图对文本轮廓的影响程度 | |
照明设置(Lighting) - 环境设置(Environment Map) | Face Color:立方体贴图对文本颜色的影响 Outline Color:立方体贴图对轮廓颜色的影响 Texture:环境立方体贴图 Rotation:旋转环境贴图 | |
发光设置(Glow) | Color:发光颜色 Offset:发光效果中心偏移值 Inner:发光效果向内延伸距离 Outer:发光效果向外延伸距离 Power:发光强度 | |
调试设置(Debug Settings) | Font Atlas:字体图集 Gradient Scale:渐变比例 Texture Width/Height:纹理宽高 Scale X/Y:SDF 比例乘数 Sharpness:清晰度 Perspective Filter:透视过滤器,使文本在透视摄像机下更柔和 Offset X/Y:每个字符顶点位置的偏移量 Mask: 关闭蒙版 硬蒙版 柔和蒙版 Clip Rect:剪辑矩形,设置遮罩矩阵范围 Stencil ID:模板 ID Stencil Comp:模板成分 Uset Ratios:使用率 Cull Mode:裁剪模式 |
4.9.MP_TextEventHandler
主要类 | 委托 | 事件 | 参数 |
---|---|---|---|
TMP_TextEventHandler | onLinkSelection | 当用户悬停或点击超链接时触发 | string linkInfo :超链接的相关信息;string linkText :超链接显示的文本;int index :超链接在文本中的索引位置 |
TMP_TextEventHandler | onCharacterSelection | 当用户悬停或点击某个字符时触发 | char charInfo :被点击或悬停的字符;int i :字符在文本中的索引位置 |
TMP_TextEventHandler | onSpriteSelection | 当用户悬停或点击某一精灵图片时触发 | char spirteInfo :与精灵图片相关的字符信息;int i :精灵图片在文本中的索引位置 |
TMP_TextEventHandler | onWordSelection | 当用户悬停或点击某个单词时触发 | string word :被点击或悬停的单词;int i1 :单词在文本中的起始索引位置;int i2 :单词在文本中的结束索引位置 |
TMP_TextEventHandler | onLineSelection | 当用户悬停或点击某一行文本时触发 | string lineInfo :被点击或悬停的行文本内容;int i1 :行在文本中的起始索引位置;int i2 :行在文本中的结束索引位置 |
4.10.TMP_TextUtilities
分类 | 详情 |
---|---|
获取给定位置文本中的具体信息 | 获取链接索引:int FindIntersectingLink(TMP_Text text, Vector3 position, Camera camera) 获取单词索引: int FindIntersectingWord(TMP_Text text, Vector3 position, Camera camera) 获取单字符索引: int FindIntersectingCharacter(TMP_Text text, Vector3 position, Camera camera) 获取行索引: int FindIntersectingLine(TMP_Text text, Vector3 position, Camera camera) |
获取离给定位置最近的文本信息 | 获取链接索引:int FindNearestLink(TMP_Text text, Vector3 position, Camera camera) 获取单词索引: int FindNearestWord(TMP_Text text, Vector3 position, Camera camera) 获取单字符索引: int FindNearestCharacterOnLine(TMP_Text text, Vector3 position, Camera camera) 获取行索引: int FindNearestLine(TMP_Text text, Vector3 position, Camera camera) |
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
public class Lesson22_TMP_TextUtilities : MonoBehaviour, IPointerClickHandler
{
public TextMeshProUGUI textMeshProUGUI;
public void OnPointerClick(PointerEventData eventData)
{
print("OnPointerClick TextMeshProUGUI");
// 获取链接索引,传入 TMP、鼠标位置、UI 摄像机(默认可以传 null)
int linkIndex = TMP_TextUtilities.FindIntersectingLink(textMeshProUGUI, eventData.position, null);
// 如果不为 -1,则证明点击到了一个超链接信息
if (linkIndex != -1)
{
// 获取超链接显示的文本信息,例如 "百度"
print(textMeshProUGUI.textInfo.linkInfo[linkIndex].GetLinkText());
// 获取富文本标签 <link=?> 中的? 具体地址信息,例如 "谷歌"
print(textMeshProUGUI.textInfo.linkInfo[linkIndex].GetLinkID());
}
// 获取单字符索引,传入 TMP、鼠标位置、UI 摄像机(默认可以传 null)、是否检测可见性
int charIndex = TMP_TextUtilities.FindIntersectingCharacter(textMeshProUGUI, eventData.position, null, true);
// 如果索引不为 -1,打印点击到的字符
if (charIndex != -1)
{
print(textMeshProUGUI.textInfo.characterInfo[charIndex].character);
}
}
}