本文介绍了Unity中的几种常用坐标系以及坐标系之间的转换方法,并在文末附上一个展示各种坐标系数据的Demo。
1. 世界(局部)坐标系
以世界原点为坐标原点建立的三维坐标系,获得GameObject世界坐标的接口为Transform.position 。局部坐标系是GameObject以Parent的世界坐标点为坐标原点建立的三维坐标系,GameObject的局部坐标即与Parent的相对位置。若GameObject无Parent,其局部坐标与世界坐标相同,获得GameObject局部坐标系的接口为Transform.localPosition。
世界坐标转化为屏幕坐标 Camera.WorldToScreenPoint
世界坐标转化为视口坐标 Camera.WorldToViewportPoint
2. 屏幕坐标系
以屏幕左下角为原点建立的一个二维坐标系,屏幕的左下角坐标为(0, 0),右上角为(Screen.width, Screen.height)。通过Input.mousePosition获取的鼠标坐标是一个屏幕坐标。
屏幕坐标转化为世界坐标 Camera.ScreenToWorldPoint
屏幕坐标转化为视口坐标 Camera.ScreenToViewportPoint
3. 视口坐标系
以屏幕左下角为原点建立的一个二维坐标系,左下角为(0, 0),右上角为(1, 1)。
视口坐标转化为世界坐标 Camera.ViewportToWorldPoint
视口坐标转化为屏幕坐标 Camera.ViewportToScreenPoint
4. GUI坐标系
以屏幕左下角为原点建立的一个二维坐标系,屏幕的左上角坐标为(0, 0),右下角为(Screen.width, Screen.height)。要注意的是,GUIUtility.ScreenToGUIPoint和GUIUtility.GUIToScreenPoint这两个接口并不是本文所描述的屏幕转标系与GUI坐标系之间的相互转换。根据Unity的官方Demo可知,这两个接口是进行屏幕的全局GUI坐标系与局部GUI坐标系(通过Rect指定)的坐标转换。
Demo效果图
鼠标在移动过程会动态显示对应的坐标,cube则在固定的位置。
代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Show Unity coordinates
public class CoordinateShow : MonoBehaviour
{
float cubeRectWidth = 230f;
float cubeRectHeight = 145f;
float mouseRectWidth = 240f;
float mouseRectHeight = 90f;
Vector2 cubeRectSize;
Vector2 mouseRectSize;
public Transform cubeTransform;
// Use this for initialization
void Start ()
{
cubeRectSize = new Vector2(cubeRectWidth, cubeRectHeight);
mouseRectSize = new Vector2(mouseRectWidth, mouseRectHeight);
}
void OnGUI()
{
ShowCubeCoord();
ShowMouseCoord();
}
void ShowCubeCoord()
{
Vector3 cubeWorldCoord = cubeTransform.position;
Vector3 cubeLocalCoord = cubeTransform.localPosition;
Vector3 cubeScreenCoord = Camera.main.WorldToScreenPoint(cubeWorldCoord);
Vector3 cubeViewportCoord = Camera.main.WorldToViewportPoint(cubeWorldCoord);
Vector2 rectGUICoord = cubeScreenCoord;
rectGUICoord.x -= cubeRectWidth / 2;
rectGUICoord.y += cubeRectHeight;
rectGUICoord.y = Screen.height - rectGUICoord.y; // Screen coordinate to GUI coordinate
GUILayout.BeginArea(new Rect(rectGUICoord, cubeRectSize));
GUILayout.Label("World Coordinate: " + cubeWorldCoord);
GUILayout.Label("Local Coordinate: " + cubeLocalCoord);
GUILayout.Label("Screen Coordinate: " + cubeScreenCoord);
GUILayout.Label("Viewport Coordinate: " + cubeViewportCoord);
GUILayout.Label("GUI Coordinate: " + rectGUICoord);
GUILayout.EndArea();
}
void ShowMouseCoord()
{
Vector3 mouseScreenCoord = Input.mousePosition;
Vector3 mouseViewportCoord = Camera.main.ScreenToViewportPoint(mouseScreenCoord);
// Mouse pointing spot in world space
Ray ray = Camera.main.ScreenPointToRay(mouseScreenCoord);
RaycastHit hit;
Physics.Raycast(ray, out hit);
Vector3 mouseWorldCoord = hit.point;
Vector2 rectGUICoord = mouseScreenCoord;
rectGUICoord.y = Screen.height - mouseScreenCoord.y; // Screen coordinate to GUI coordinate
// Show the complete GUI area
if (rectGUICoord.x < 0)
rectGUICoord.x = 0;
if (rectGUICoord.x > Screen.width - mouseRectWidth)
rectGUICoord.x = Screen.width - mouseRectWidth;
if (rectGUICoord.y < 0)
rectGUICoord.y = 0;
if (rectGUICoord.y > Screen.height - mouseRectHeight)
rectGUICoord.y = Screen.height - mouseRectHeight;
GUILayout.BeginArea(new Rect(rectGUICoord, mouseRectSize));
GUILayout.Label("World Coordinate: " + mouseWorldCoord);
GUILayout.Label("Screen Coordinate: " + mouseScreenCoord);
GUILayout.Label("Viewport Coordinate: " + mouseViewportCoord);
GUILayout.Label("GUI Coordinate: " + rectGUICoord);
GUILayout.EndArea();
}
}
void OnGUI()
{
ShowCubeCoord();
ShowMouseCoord();
}
void ShowCubeCoord()
{
Vector3 cubeWorldCoord = cubeTransform.position;
Vector3 cubeLocalCoord = cubeTransform.localPosition;
Vector3 cubeScreenCoord = Camera.main.WorldToScreenPoint(cubeWorldCoord);
Vector3 cubeViewportCoord = Camera.main.WorldToViewportPoint(cubeWorldCoord);
Vector2 rectGUICoord = cubeScreenCoord;
rectGUICoord.x -= cubeRectWidth / 2;
rectGUICoord.y += cubeRectHeight;
rectGUICoord.y = Screen.height - rectGUICoord.y; // Screen coordinate to GUI coordinate
GUILayout.BeginArea(new Rect(rectGUICoord, cubeRectSize));
GUILayout.Label("World Coordinate: " + cubeWorldCoord);
GUILayout.Label("Local Coordinate: " + cubeLocalCoord);
GUILayout.Label("Screen Coordinate: " + cubeScreenCoord);
GUILayout.Label("Viewport Coordinate: " + cubeViewportCoord);
GUILayout.Label("GUI Coordinate: " + rectGUICoord);
GUILayout.EndArea();
}
void ShowMouseCoord()
{
Vector3 mouseScreenCoord = Input.mousePosition;
Vector3 mouseViewportCoord = Camera.main.ScreenToViewportPoint(mouseScreenCoord);
// Mouse pointing spot in world space
Ray ray = Camera.main.ScreenPointToRay(mouseScreenCoord);
RaycastHit hit;
Physics.Raycast(ray, out hit);
Vector3 mouseWorldCoord = hit.point;
Vector2 rectGUICoord = mouseScreenCoord;
rectGUICoord.y = Screen.height - mouseScreenCoord.y; // Screen coordinate to GUI coordinate
// Show the complete GUI area
if (rectGUICoord.x < 0)
rectGUICoord.x = 0;
if (rectGUICoord.x > Screen.width - mouseRectWidth)
rectGUICoord.x = Screen.width - mouseRectWidth;
if (rectGUICoord.y < 0)
rectGUICoord.y = 0;
if (rectGUICoord.y > Screen.height - mouseRectHeight)
rectGUICoord.y = Screen.height - mouseRectHeight;
GUILayout.BeginArea(new Rect(rectGUICoord, mouseRectSize));
GUILayout.Label("World Coordinate: " + mouseWorldCoord);
GUILayout.Label("Screen Coordinate: " + mouseScreenCoord);
GUILayout.Label("Viewport Coordinate: " + mouseViewportCoord);
GUILayout.Label("GUI Coordinate: " + rectGUICoord);
GUILayout.EndArea();
}
}