坐标系
概要
世界坐标
transform.position 游戏中获取的就是世界坐标。
局部/本地坐标
transform.localPosition
本地坐标系的特点是:
- 原点位于游戏对象的position属性指定的位置。
- 使用游戏对象自身的transform组件定义的Orientation(方向)。
- 本地坐标系是相对于父对象坐标系的,如果没有父对象,则相对于世界坐标系。
- 当对象位置或旋转时,本地坐标系也会跟着改变。
- 对象的scale属性也会缩放本地坐标系。
本地坐标系经常用于:
- 指定对象相对自身的偏移量,如使用LocalPosition。
- 作为对象内部组件的相对坐标系,如相机、碰撞体等组件。
- 用作计算对象本身的运算坐标系。
- 表示对象空间下的点、矢量等。
总之,Unity中的本地坐标系是相对游戏对象自身的坐标系统,用于表示对象内部的相对关系,是一个非常重要的概念
屏幕坐标系
屏幕坐标就是相对于游戏的屏幕来说的,最大和游戏分辨率相等。
获取鼠标的位置是屏幕坐标
视口坐标系
视口坐标系和屏幕坐标系完全对等,不过范围是0-1。
GUI坐标系
和屏幕坐标系最大值一样,只不过y轴的方向相反,是从上到下。
别名
- 世界坐标(全局坐标、左手坐标、绝对坐标)
- 本地坐标(局部坐标、自身坐标、物体坐标、相对坐标)
- 屏幕坐标(像素坐标)
- 视口坐标(视窗坐标)
- GUI坐标(UI坐标)
示例代码
1 | private void OnGUI() |
坐标转换
屏幕坐标和视口坐标
Input.mousePosition
鼠标的位置是屏幕坐标
屏幕坐标=>视口坐标
1 | mainCamera.ScreenToViewportPoint(Input.mousePosition) |
视口坐标=>屏幕坐标
1 | Vector3 screenPoint = mainCamera.ViewportToScreenPoint |
屏幕坐标和世界坐标
世界坐标=>屏幕坐标
1 | Vector3 wPos = mCamera.WorldToScreenPoint(pPos); |
屏幕坐标=>世界坐标
直接调用相机的屏幕转世界是不行的,因为我们获取到的屏幕坐标是没有z值的,所以计算的都是错的。
对于2D可以采用下面的方法,因为z是不变的。
1 | /// <summary> |
GUI/Gizmos/Debug/Handles绘制及对比
GUI绘制
GUI绘制使用的是GUI坐标。
示例
1 | private void OnGUI() |
Gizmos绘制
OnDrawGizmosSelected和OnDrawGizmos使用其一即可。
- OnDrawGizmosSelected 元素选中时才显示
- OnDrawGizmos 都显示
但是无论哪种方式都要在开始调试后,让右上角的Gizmos处于激活状态才能显示。
并且只能放在这两个方法内,不能在OnGUI
中。
1 | private void OnDrawGizmosSelected() |
在 Unity 中,可以通过 Gizmos 类在 Scene 视图中绘制各种调试图形,常见的有:
- 线条:Gizmos.DrawLine
- 方框:Gizmos.DrawWireCube
- 方形:Gizmos.DrawCube
- 圆环:Gizmos.DrawWireSphere
- 球体:Gizmos.DrawSphere
- 射线:Gizmos.DrawRay
- 网格:Gizmos.DrawMesh
- 扇形:Gizmos.DrawFrustum
- 相机视锥:Gizmos.DrawIcon
绘制线
1 | Gizmos.color = Color.red; |
绘制框
1 | Gizmos.color = Color.red; |
绘制圆环(中空)
1 | Gizmos.color = Color.red; |
绘制球(实心)
1 | Gizmos.color = Color.red; |
绘制射线
1 | Gizmos.DrawRay(transform.position, Vector3.right * 6); |
从源码中我们可以看到本质还是画线
1 | public static void DrawRay(Vector3 from, Vector3 direction) => Gizmos.DrawLine(from, from + direction); |
Debug绘制
Debug绘制使用的世界坐标
右上角的Gizmos处于激活状态才能显示。
1 | private void DrawLine() |
或者
这个和上面的效果是一样的。
1 | private void DrawLine() |
Handles绘制
Handles使用的世界坐标,但是注意绘制图形的时候需要设置相机,绘制Label的时候不需要设置相机。
绘制Label
比如在我们的人物上显示名称
1 | private void OnGUI() |
绘制圆
1 | private void OnGUI() |
绘制线
1 | private void OnGUI() |
使用场景
概要
GUI、Gizmos 和 Handles 在 Unity 中的主要使用场景如下:
GUI - 用于在游戏界面中创建UI元素,如按钮、文本等。适用于显示游戏信息,提供交互。
使用GUI坐标系。
示例:
1 | void OnGUI() { |
Gizmos - 用于在场景编辑器中可视化辅助信息,如球体、线条等。
使用世界坐标系。
示例:
1 | void OnDrawGizmos() { |
Handles - 用于在场景编辑器中可视化交互编辑信息,如移动、旋转控制器。
使用世界坐标系。
示例:
1 | void OnSceneGUI() { |
Debug.DrawLine 和 Gizmos.DrawLine
Debug.DrawLine 和 Gizmos.DrawLine 都是用于在 Unity 编辑器中绘制线条的方法,它们有以下几点主要区别:
- 绘制时机
Debug.DrawLine 是在运行时绘制,也就是在游戏运行时绘制,可以用来在场景中临时绘制一些辅助线条。
Gizmos.DrawLine 是在设计时绘制,在场景编辑模式下绘制,主要用于可视化辅助。 - 持续时间
Debug.DrawLine 绘制的线条只会持续一个帧。
Gizmos.DrawLine 绘制的线条会持续显示直到再次编译代码或进入播放模式。 - 可用性
Debug.DrawLine 可以在任何环境下使用。
Gizmos.DrawLine 只能在编辑器中使用。
主要的使用时机如下:
- 如果需要在游戏运行时绘制临时辅助线条,用于Debug,选择 Debug.DrawLine。
- 如果需要在编辑器模式下持续显示的辅助线条,用于场景可视化,选择 Gizmos.DrawLine。
- 如果需要可在编辑器和运行时都使用的线条绘制功能,可以封装一下,根据情况调用上面两种方法。
总结
使用GUI坐标系的
- GUI用于游戏运行时界面
使用世界坐标系的
Debug.DrawLine用于游戏运行时界面
Gizmos用于场景编辑的可视化信息
Handles用于场景编辑的交互控制
明确每一个的适用场景,可以更好地在Unity中使用它们实现各自的功能。