【Unity基础】Unity中的Pivot vs Center 小实验步骤列表 + 截图指引
目标:通过一系列可重复、可截图、可对比的小实验,直观理解 Unity 编辑器工具栏中的 Pivot / Center 与 Local / Global 对移动、旋转、缩放操作的影响;并区分“对象真实枢轴点(Transform.position / Sprite Pivot / RectTransform Pivot)”与“集合包围盒中心(Selection Bounds Center)”。
快速导航
- 0. 预备知识复习卡
- 1. 实验环境准备
- 2. 测试资源快速创建
- 3. 基础场景布置
- 4. 实验A:单对象 Pivot vs Center (3D)
- 5. 实验B:修改 Sprite Pivot 并观察差异 (2D)
- 6. 实验C:多选对象 Pivot/Center × Local/Global 旋转对比
- 7. 实验D:多选缩放行为差异
- 8. 实验E:UI RectTransform Pivot 与锚点实验
- 9. 空父物体重设 Pivot 技巧
- 10. 数据记录表(可复制)
- 11. 常见问题排雷
- 12. 扩展练习 & 思考题
0. 预备知识复习卡
⚡ 核心记忆(强烈建议背下来)
- Pivot = 本地坐标系原点 (local 0,0,0)。 所有局部旋转 / 缩放轴、子物体
localPosition
的参照点都以它为基准。 - Inspector 中 Position =
transform.localPosition
= 相对于父对象本地原点(父 Pivot)的坐标。 若对象无父,则该值等于世界坐标 (transform.position
)。
换句话说:父对象的 Pivot 就是子坐标系的 (0,0,0)。 这正是我们可以用“空父对象”来重设一组物体旋转中心的原因。
简图(父→子坐标):
父 (Pivot@P_world)└─ 子.localPosition = Δ (在 Inspector Position 显示)子.worldPosition = 父.worldMatrix * Δ
下面是快速模式速查:
Pivot 模式:编辑器手柄位于“活动对象”的真实枢轴(通常 = Transform.position)。 Center 模式:手柄位于所有选中对象的世界包围盒中心(不改变真实 Pivot)。 Local:工具轴对齐到活动对象本地坐标系。 Global:工具轴对齐到世界坐标系。
多选时,Pivot 模式的手柄落在活动对象;Center 模式落在集合中心。旋转/缩放结果因 Local/Global 再细分,详见各实验。
Pivot 模式:编辑器手柄位于“活动对象”的真实枢轴(通常 = Transform.position)。 Center 模式:手柄位于所有选中对象的世界包围盒中心(不改变真实 Pivot)。 Local:工具轴对齐到活动对象本地坐标系。 Global:工具轴对齐到世界坐标系。
多选时,Pivot 模式的手柄落在活动对象;Center 模式落在集合中心。旋转/缩放结果因 Local/Global 再细分,详见各实验。
1. 实验环境准备
Unity 版本:任意 2021 LTS+(示例基于 URP 3D 模板;2D 项目亦可)。
推荐项目结构
Assets/_Labs/PivotCenter/Materials/Sprites/Prefabs/Scenes/
必开窗口:
- Scene View(工具栏需可见)
- Game View
- Hierarchy
- Inspector
- Gizmos(Scene 视图右上角开)
截图建议快捷键:操作系统级截图或 Unity Recorder / 第三方工具。
2. 测试资源快速创建
2.1 3D 测试资源
GameObject > 3D Object > Cube
,命名Cube_A
。- 复制生成
Cube_B
。 - 创建
GameObject > 3D Object > Cylinder
,命名PivotMarker
(可缩小缩放到 0.2 便于视觉标记)。 - 给 A / B 分配不同颜色材质(红 / 蓝),方便区分。
2.2 2D Sprite 测试资源(可选)
-
新建 128×128 PNG(透明背景,填充不同色块)。
-
在 Sprite Editor 里制作两个版本:
Sprite_CenterPivot
:Pivot=Center。Sprite_BottomLeftPivot
:Pivot=Bottom Left 或 Custom(0,0)。
2.3 UI 测试资源
GameObject > UI > Canvas
。- 创建 Button 命名
Btn_Default
。 - 复制为
Btn_CustomPivot
;在 RectTransform 中修改 Pivot 值(如 0,0)。
3. 基础场景布置
在 Scenes/
下新建场景:PivotCenterLab
。
3.1 世界原点参照
- 在 (0,0,0) 放一个空对象
WorldOrigin
(可添加小型 Gizmo)。
3.2 摆放 3D 测试物体
对象 | 位置 (x,y,z) | 说明 |
---|---|---|
Cube_A | (0, 0, 0) | 基准物体,靠近世界原点 |
Cube_B | (3, 0, 0) | 位于 +X 方向 |
PivotMarker | (-2, 0, 0) | 用来演示“人为 Pivot”(配空父) |
截图要点:Scene 视图中能看见 XYZ 轴、3 个物体及坐标。
3.3 摄像机对齐
- 在 Scene 视图中右键相机
Main Camera > Align With View
,保证 3D 实验截图一致。
4. 实验A:单对象 Pivot vs Center (3D)
目的:观察单物体在工具栏切换 Pivot/Center 时,手柄位置如何变化;同时记录 Transform.position 与 Renderer.bounds.center 差值。
步骤
- 单选
Cube_A
。 - 工具栏切换 Pivot。观察:手柄位于 Cube_A Transform.position(即几何中心 除非模型原点偏移)。
- 切换 Center。观察:手柄位于 Cube_A 的渲染包围盒中心。
- 在 Inspector 记录:Transform.position。
- 在调试脚本中打印:
GetComponent<Renderer>().bounds.center
。
记录(示例表)
模式 | Scene 手柄位置 | Transform.position | Renderer.bounds.center | 差值 |
---|---|---|---|---|
Pivot | (0,0,0) | (0,0,0) | (0,0,0) | 0 |
Center | (0,0,0) | (0,0,0) | (0,0,0) | 0 |
如果是导入模型(原点不在几何中心),Center 模式与 Pivot 模式会出现明显差异 —— 截图捕捉这一点很有价值。
截图要点
- Scene 工具栏红框标出 Pivot / Center 按钮。
- 手柄在立方体内部的位置对比(两张图)。
- Inspector 面板截图(Transform 值)。
5. 实验B:修改 Sprite Pivot 并观察差异 (2D)
目的:验证 资源级 Pivot 改动 会改变实例 Transform 对齐位置,从而影响 Pivot 模式下手柄位置,但不影响 Center 模式。
场景准备
切换到 2D Scene 模式(Scene 视图左上 2D 按钮)。
步骤
- 将
Sprite_CenterPivot
拖入场景,命名Spr_Center
,位置 (0,0,0)。 - 将
Spr_BottomLeftPivot
拖入场景,命名Spr_BL
,位置 (3,0,0)。 - 单选 Spr_BL,切换 Pivot 模式:手柄应出现在图片左下角(贴边)。
- 切换 Center 模式:手柄跳到图像矩形中心。
- 重新编辑资源 Pivot:在 Project 里选 Sprite,Sprite Editor 中改 Pivot=Top Right,Apply。
- 回场景查看实例:若引用更新,Pivot 模式手柄应随新 Pivot 改变。
注意:若场景实例未自动更新,重新拖拽或手动 Reimport。
截图要点
- Sprite Editor 的 Pivot 下拉框位置。
- Scene 视图中 Pivot / Center 手柄对比(至少 2 图)。
6. 实验C:多选对象 Pivot/Center × Local/Global 旋转对比
目的:理解四种组合对旋转行为的影响。
准备
- 在 3D 场景中选择
Cube_A
与Cube_B
(按住 Ctrl/Command 多选)。 - 确认
Cube_B
为活动对象(最后点击,使其高亮更亮)。 - 切到 Rotate Tool (E)。
测试矩阵
依次执行四组:
- Pivot + Local
- Pivot + Global
- Center + Local
- Center + Global
每组操作:
- 先复位:撤销到两个方块回原位置 (Ctrl+Z) 或手动重置 Transform。
- 设置工具栏模式。
- 在 Scene 中将对象旋转 45° 绕 Y。
- 观察:每个方块是否原地自转?是否绕公共中心公转?
- 记录旋转后 Transform.position(特别是 X 坐标变化)。
预期现象速查
组合 | 预计行为(简化版) |
---|---|
Pivot + Local | 两个方块基本原地各自旋转;位置不绕中心移动。 |
Pivot + Global | 各自以自身 Pivot 绕世界 Y 旋转;通常与上类似(若本地轴已旋转会不同)。 |
Center + Local | 群体绕集合中心旋转(轴参考活动对象本地方向);位置改变。 |
Center + Global | 群体绕集合中心按世界轴旋转;位置显著改变——最直观的“像组合件一样转”。 |
截图要点
- 每组前后各 1 图(建议 4 组共 8 图)。
- Scene 工具栏状态清晰可见。
- 可打开 Gizmos 显示旋转轨迹(可画辅助线)。
7. 实验D:多选缩放行为差异
目的:比较 Pivot 与 Center 模式下缩放对对象间距与相对尺寸的影响。
步骤
- 重置 Cube_A(0,0,0) & Cube_B(3,0,0)。
- 激活 Scale Tool ®。
D1:Pivot 模式缩放
- 模式:Pivot + Global(或 Local)。
- 选中 A+B,活动对象=Cube_B。
- 沿统一轴缩放到 2 倍。
- 观察:两个方块各自按自身 Pivot 缩放;它们之间中心距(约 3 单位)保持不变。
D2:Center 模式缩放
- 模式:Center + Global。
- 同样选中 A+B,缩放 2 倍。
- 观察:它们绕集合中心展开(间距被拉大到 6 单位左右,因位置向外缩放)。
对比前后坐标并截图。
记录表
组合 | A 缩放前 pos.x | A 缩放后 pos.x | B 缩放前 pos.x | B 缩放后 pos.x | 间距变化 |
---|---|---|---|---|---|
Pivot | 0 | 0 | 3 | 3 | 3→3 |
Center | 0 | -1.5 | 3 | 4.5 | 3→6 |
(示例:以集合中心 1.5 缩放 2× 推算)
8. 实验E:UI RectTransform Pivot 与锚点实验
目的:理解 UI Pivot 改变时元素在 Canvas 内的位置与动画效果。
布置
- Canvas = Screen Space - Overlay。
- 创建两个 Button:
Btn_Default
(Pivot=0.5,0.5),Btn_CustomPivot
(Pivot=0,0)。 - 把两个按钮放在可见区域左上 & 右下,便于观察。
步骤
-
单选
Btn_CustomPivot
。 -
在 RectTransform Inspector 下拉“Anchors Presets”设为
Center
;记录 Anchored Pos。 -
改 Pivot 从 (0,0) → (1,1)。观察:按钮在场景中会发生位置跳变(锚点 & pivot 共同影响 anchoredPosition 的解释方式)。
-
在动画窗口对按钮做 Scale 0→1 动画:
- Pivot=中心:按钮从中心放大。
- Pivot=左下:按钮从左下角向右上方展开。
截图要点
- RectTransform Inspector(Pivot 字段变更前后)。
- Scene Canvas 中按钮可视位置前后对比。
- 动画播放帧对比(可选)。
9. 空父物体重设 Pivot 技巧
当资源 Pivot 不可轻易修改(或多个子物体需共享新枢轴)时:
步骤
- 在层级视图创建空对象
NewPivot
,放到你希望的旋转点(例如 (-2,0,0))。 - 将
Cube_A
与Cube_B
拖为其子级;调整其局部坐标保持视觉不变。 - 操作
NewPivot
的 Transform 即可使群体绕此新枢轴旋转/缩放。
对比
- 与 Center 模式不同:空父提供了稳定、可动画化、可脚本控制的真实枢轴 GameObject。
截图要点
- 层级结构树(NewPivot > Cube_A, Cube_B)。
- Scene 中手柄对准 NewPivot。
10. 数据记录表(可复制)
复制下表到 Excel / Notion / Google Sheet 做实验数据记录。
10.1 单对象
对象 | 模式 | 手柄位置 | Transform.position | Renderer/Sprite.bounds.center | 差值 |
---|
10.2 多对象旋转
序号 | 模式组合 | 操作轴 | A 初始 Pos | B 初始 Pos | A 结果 Pos | B 结果 Pos | 行为描述 |
---|
10.3 多对象缩放
序号 | 模式组合 | 缩放系数 | A 前 PosX | A 后 PosX | B 前 PosX | B 后 PosX | 间距变化 |
---|
10.4 UI Pivot 实验
元素 | 初始 Pivot | 新 Pivot | Anchors | 改前 Pos | 改后 Pos | 可视变化 | 备注 |
---|
11. 常见问题排雷
问题 | 可能原因 | 解决方法 |
---|---|---|
改了 Sprite Pivot 但场景没变化 | 场景中实例引用旧资源缓存 | Reimport & 重新拖入;或 Sprite Variant。 |
多选旋转乱跑 | 当前为 Center 模式 | 切回 Pivot;或先建父对象。 |
UI Pivot 改动导致位置跳 | 锚点与 Pivot 相互作用 | 改前记下 Anchored Pos;使用 “Set Native Size” 或 Layout 工具。 |
旋转工具轴方向怪 | Local/Global 设置 | 确认工具栏状态;活动对象是谁。 |
12. 扩展练习 & 思考题
练习 1:导入偏移原点模型
- 在 Blender 把立方体放离世界原点 2m,再导入 Unity。
- 观察:Pivot 模式手柄在 Transform(导入原点),而立方体网格在远处;Center 模式落在几何体附近。
练习 2:程序化打印差异
using UnityEngine;public class PivotCenterProbe : MonoBehaviour
{void OnDrawGizmosSelected(){var r = GetComponent<Renderer>();if (r == null) return;Gizmos.color = Color.yellow; // Transform.positionGizmos.DrawSphere(transform.position, 0.1f);Gizmos.color = Color.cyan; // Renderer.bounds.centerGizmos.DrawSphere(r.bounds.center, 0.1f);}
}
将此脚本挂到对象上,进入 Scene 选择它时即可可视化两点差异。
练习 3:运行时旋转对照
- 写脚本:按键 1 围绕 transform 自转;按键 2 围绕公共点旋转(通过
RotateAround
)。比较与编辑器 Pivot/Center 类似的行为。
结语
完成以上实验后,你应能:
- 一眼判断当前 Scene 操作受哪个模式控制;
- 快速诊断“为什么我一旋,东西飞了”的问题;
- 为动画与脚本控制设计可靠 Pivot(通过空父 / 资源导入 / RectTransform Pivot);
- 用 Center + Global 对群体排版、缩放、对齐,之后再切 Pivot 精修。
如需:我可以帮你制作操作检查清单 PDF、自动化 Gizmo 扫描工具、或教学课件 PPT。告诉我下一步!
附录:打印 Renderer.bounds
与 Transform.position
的 Editor 脚本
下面的 Editor 工具可帮助你对比对象真实 Pivot(Transform.position)与其渲染几何包围盒中心 (``),并计算多选集合的整体包围盒中心(即 Scene 工具栏 Center 模式所依据的近似值)。
功能
-
针对当前 Selection 中的所有 GameObject:
- 打印世界空间
Transform.position
(真实 Pivot)。 - 聚合其自身及子层级
Renderer
的包围盒(若有)。 - 输出
Renderer.bounds.center / size
。
- 打印世界空间
-
计算整个选择集的合并包围盒(Selection Bounds)。
-
标记活动对象(
Selection.activeTransform
)。 -
提供 场景 Gizmo 可视化:在每个 Transform.position 与 Bounds.center 画射线 / 球点,便于截图。
将脚本放入:
Assets/Editor/SelectionBoundsDiagnostics.cs
(必须在 Editor 文件夹中)。
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;/// <summary>
/// 工具:打印当前选择集中每个对象的 Transform(Pivot) 与 Renderer.bounds(Center),并绘制可视化 Gizmo。
/// 用于理解 Unity 工具栏 Pivot / Center 行为。
/// </summary>
public static class SelectionBoundsDiagnostics
{private const string MenuRoot = "Tools/Pivot-Center Diagnostics/";/// <summary>/// 在 Console 中打印选择信息。/// </summary>[MenuItem(MenuRoot + "Print Selection Bounds")] public static void PrintSelectionBounds(){var objs = Selection.gameObjects;if (objs == null || objs.Length == 0){Debug.Log("[PivotCenter] 当前没有选中任何对象。");return;}Transform active = Selection.activeTransform;Debug.Log($"[PivotCenter] 当前选中 {objs.Length} 个对象;活动对象 = {(active ? active.name : "<null>")}");// --- 合并全局包围盒(模拟 Scene 工具栏 Center 使用的 Selection Bounds) ---bool hasAnyBounds = false;Bounds selectionBounds = default;foreach (var go in objs){if (TryGetHierarchyBounds(go, out Bounds b)){if (!hasAnyBounds){selectionBounds = b;hasAnyBounds = true;}else{selectionBounds.Encapsulate(b);}}}if (hasAnyBounds){Debug.Log($"[PivotCenter] **Selection Bounds** center={selectionBounds.center:F3} size={selectionBounds.size:F3} extents={selectionBounds.extents:F3}");}else{Debug.LogWarning("[PivotCenter] 选择集中没有找到任何 Renderer 可计算包围盒;Center 模式在场景中可能仍显示手柄(Unity 内部可能使用不同策略)。");}// --- 逐对象打印 ---foreach (var go in objs){Transform t = go.transform;string prefix = (active == t) ? "[ACTIVE]" : " ";// Transform(Pivot)Vector3 pivot = t.position;// Renderer boundsstring boundsInfo;if (TryGetHierarchyBounds(go, out Bounds hb)){boundsInfo = $"bounds.center={hb.center:F3} size={hb.size:F3}";}else{boundsInfo = "(no Renderer)";}Debug.Log($"{prefix} {go.name} :: pivot(Transform.position)={pivot:F3} :: {boundsInfo}");}}/// <summary>/// 聚合 GameObject 及其全部子层级中的所有 Renderer.bounds;若无 Renderer 返回 false。/// </summary>private static bool TryGetHierarchyBounds(GameObject go, out Bounds bounds){var renderers = go.GetComponentsInChildren<Renderer>();if (renderers == null || renderers.Length == 0){bounds = default;return false;}bounds = renderers[0].bounds;for (int i = 1; i < renderers.Length; i++){bounds.Encapsulate(renderers[i].bounds);}return true;}// ======================================================================// Scene 可视化(Gizmos):通过 SceneView.duringSceneGui 绘制当前选择信息// ======================================================================[InitializeOnLoadMethod]private static void InitSceneHook(){SceneView.duringSceneGui -= OnSceneGUI;SceneView.duringSceneGui += OnSceneGUI;}private static void OnSceneGUI(SceneView sv){Handles.zTest = UnityEngine.Rendering.CompareFunction.Always; // 确保可见var objs = Selection.gameObjects;if (objs == null || objs.Length == 0) return;Transform active = Selection.activeTransform;// 绘制 Selection 合并包围盒if (TryGetSelectionBounds(objs, out Bounds sb)){Handles.color = new Color(1f, 0.8f, 0f, 0.8f); // 橙色Handles.DrawWireCube(sb.center, sb.size);Handles.SphereHandleCap(0, sb.center, Quaternion.identity, HandleUtility.GetHandleSize(sb.center) * 0.1f, EventType.Repaint);Handles.Label(sb.center + Vector3.up * HandleUtility.GetHandleSize(sb.center) * 0.2f, "Selection Center");}// 绘制每个对象的 Pivot & HierarchyBounds.centerforeach (var go in objs){Transform t = go.transform;bool isActive = (t == active);Vector3 pivot = t.position;float hSize = HandleUtility.GetHandleSize(pivot) * 0.075f;Handles.color = isActive ? Color.green : Color.cyan;Handles.SphereHandleCap(0, pivot, Quaternion.identity, hSize, EventType.Repaint);Handles.Label(pivot + Vector3.up * hSize * 1.25f, isActive ? $"{go.name} (Pivot) [ACTIVE]" : $"{go.name} (Pivot)");if (TryGetHierarchyBounds(go, out Bounds hb)){Vector3 c = hb.center;float cSize = HandleUtility.GetHandleSize(c) * 0.05f;Handles.color = new Color(1f, 0f, 1f, 0.9f); // 品红 = bounds centerHandles.CubeHandleCap(0, c, Quaternion.identity, cSize, EventType.Repaint);Handles.DrawDottedLine(pivot, c, 2f);}}}private static bool TryGetSelectionBounds(GameObject[] objs, out Bounds selectionBounds){bool has = false;selectionBounds = default;foreach (var go in objs){if (TryGetHierarchyBounds(go, out Bounds b)){if (!has){selectionBounds = b;has = true;}else{selectionBounds.Encapsulate(b);}}}return has;}
}
#endif
使用步骤
-
在项目中创建文件夹:
Assets/Editor/
(若已有可复用)。 -
新建 C# 脚本
SelectionBoundsDiagnostics.cs
,粘贴上方代码,保存。 -
回到 Unity,等待编译完成。
-
在层级面板选中 1 个或多个对象。
-
菜单:Tools ▸ Pivot-Center Diagnostics ▸ Print Selection Bounds。
-
打开 Console 查看输出差异:
[PivotCenter] 当前选中 2 个对象;活动对象 = Cube_A [PivotCenter] **Selection Bounds** center=(0.500,0.500,0.000) size=(2.000,1.000,1.000) ...Cube_B :: pivot(Transform.position)=(1.000,0.000,0.000) :: bounds.center=(1.500,0.500,0.000) size=(1.000,1.000,1.000) [ACTIVE] Cube_A :: pivot(Transform.position)=(0.000,0.000,0.000) :: bounds.center=(0.500,0.500,0.000) size=(1.000,1.000,1.000)
-
在 Scene 视图里切换工具栏 Pivot/Center / Local/Global,观察:
- Gizmo 中绿色/青色球 = 每个对象 Pivot。
- 品红色小方块 = 对象层级 Renderer.bounds.center。
- 橙色线框盒 = Selection Bounds(近似 Center 手柄位置)。
建议配合你之前的实验场景(例如两个不同 Pivot 的 Sprite)一起使用,截图前切换 Pivot/Center 并对比 Scene 手柄位置与 Gizmo 标记点。