世界坐标
transform.position 游戏中获取的就是世界坐标。
局部/本地坐标
transform.localPosition
本地坐标系的特点是:
本地坐标系经常用于:
总之,Unity中的本地坐标系是相对游戏对象自身的坐标系统,用于表示对象内部的相对关系,是一个非常重要的概念
屏幕坐标系
屏幕坐标就是相对于游戏的屏幕来说的,最大和游戏分辨率相等。
获取鼠标的位置是屏幕坐标
视口坐标系
视口坐标系和屏幕坐标系完全对等,不过范围是0-1。
GUI坐标系
和屏幕坐标系最大值一样,只不过y轴的方向相反,是从上到下。
private void OnGUI()
{
Camera mainCamera = Camera.main;
GUI.contentColor = Color.black;
GUI.skin.label.fontSize = 20;
GUI.Label
(
new Rect
(
10,
10,
400,
30
),
"世界坐标:" + transform.position
);
GUI.Label
(
new Rect
(
10,
40,
400,
30
),
"局部/本地坐标:" + transform.localPosition
);
GUI.Label
(
new Rect
(
10,
70,
400,
30
),
"屏幕宽高:" + Screen.width + "x" + Screen.height
);
GUI.Label
(
new Rect
(
10,
100,
400,
30
),
"屏幕坐标-鼠标位置:" + Input.mousePosition
);
GUI.Label
(
new Rect
(
10,
130,
400,
30
),
"视口坐标-鼠标位置:" + mainCamera.ScreenToViewportPoint(Input.mousePosition)
);
}
Input.mousePosition
鼠标的位置是屏幕坐标
屏幕坐标=>视口坐标
mainCamera.ScreenToViewportPoint(Input.mousePosition)
视口坐标=>屏幕坐标
Vector3 screenPoint = mainCamera.ViewportToScreenPoint
(
new Vector3
(
0.5,
0.5,
0
)
);
世界坐标=>屏幕坐标
Vector3 wPos = mCamera.WorldToScreenPoint(pPos);
屏幕坐标=>世界坐标
直接调用相机的屏幕转世界是不行的,因为我们获取到的屏幕坐标是没有z值的,所以计算的都是错的。
对于2D可以采用下面的方法,因为z是不变的。
/// <summary>
/// 屏幕转世界
/// </summary>
/// <param name="sPos">世界坐标</param>
/// <param name="mCamera">相机</param>
/// <param name="pPos">世界坐标下任意对象的位置,主要获取z值</param>
/// <returns></returns>
private Vector3 ScreenToWord
(
Vector3 sPos,
Camera mCamera,
Vector3 pPos
)
{
//因为屏幕坐标没有z值,所以我们线获取世界转屏幕时的z值
Vector3 wsPos = mCamera.WorldToScreenPoint(pPos);
sPos.z = wsPos.z;
//设置z值后就能使用屏幕转世界了。
return mCamera.ScreenToWorldPoint(sPos);
}
GUI绘制使用的是GUI坐标。
示例
private void OnGUI()
{
Camera mainCamera = Camera.main;
GUI.contentColor = Color.black;
GUI.skin.label.fontSize = 20;
GUI.Label
(
new Rect
(
10,
10,
400,
30
),
"世界坐标:" + transform.position
);
}
OnDrawGizmosSelected和OnDrawGizmos使用其一即可。
但是无论哪种方式都要在开始调试后,让右上角的Gizmos处于激活状态才能显示。
并且只能放在这两个方法内,不能在OnGUI
中。
private void OnDrawGizmosSelected()
{
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
//绘制线
Gizmos.DrawLine(transform.position, transform.position + Vector3.right);
//绘制框
Gizmos.DrawWireCube
(
transform.position,
new Vector3
(
2,
2,
2
)
);
}
Handles使用的世界坐标,但是注意绘制图形的时候需要设置相机,绘制Label的时候不需要设置相机。
绘制Label
比如在我们的人物上显示名称
private void OnGUI()
{
Handles.Label(transform.position, "小明");
}
绘制圆
private void OnGUI()
{
Camera mainCamera = Camera.main;
Handles.color = Color.red;
Handles.SetCamera(mainCamera);
Handles.RadiusHandle
(
Quaternion.identity,
transform.position,
2
);
}
绘制线
private void OnGUI()
{
Camera mainCamera = Camera.main;
Handles.color = Color.red;
Handles.SetCamera(mainCamera);
Handles.lighting = true;
Vector3 startPoint = transform.position;
Vector3 endPoint = startPoint + transform.right * 2;
Handles.DrawLine
(
startPoint,
endPoint
);
}
GUI、Gizmos 和 Handles 在 Unity 中的主要使用场景如下:
GUI - 用于在游戏界面中创建UI元素,如按钮、文本等。适用于显示游戏信息,提供交互。
使用GUI坐标系。 示例:
void OnGUI() {
GUI.Button(new Rect(100,100,200,50), "Start Game");
}
Gizmos - 用于在场景编辑器中可视化辅助信息,如球体、线条等。
使用世界坐标系。 示例:
void OnDrawGizmos() {
Gizmos.DrawWireSphere(transform.position, 10);
}
Handles - 用于在场景编辑器中可视化交互编辑信息,如移动、旋转控制器。
使用世界坐标系。 示例:
void OnSceneGUI() {
Handles.DoPositionHandle(transform.position, transform.rotation);
}
总结:
明确三者的适用场景,可以更好地在Unity中使用它们实现各自的功能。