坐标系转化
坐标系
在3D数学坐标系中,提到了以下3种坐标系。
- 世界坐标系:以大家公认的原点和轴向建立的坐标系。
- 物体坐标系:以物体位置和自身轴向建立的坐标系。
- 惯性坐标系:以物体位置和世界坐标系轴向建立的坐标系。
[截图]
世界坐标系
- Unity的Scene面板中(0,0,0)的位置就是世界坐标系的原点。
- 右上角示意图指明了世界坐标系的轴向。
[截图]
transform.position; // 世界坐标系中物体的位置
transform.forward; // 世界坐标系中物体的前方
物体坐标系
- 选择一个物体时,检视面板Transform下的Position、Rotation、Scale指的是它在父物体坐标系中的位置、旋转、缩放。
- 当一个物体没有指定父物体时,它的父物体就是世界。也就是说这时检视面板Transform下的Position正好是它在世界坐标系中的位置。
- Unity引擎中物体保存的都是相对于父物体坐标系中的数据,所以当父物体变化(移动、旋转、缩放)时,子物体会同步变化。
[截图Transfrom面板]
transform.localPosition; // 在父物体坐标系中的位置
transform.localRotation; // 在父物体坐标系中的旋转
transform.localScale; // 在父物体坐标系中的缩放
屏幕坐标系
- 屏幕坐标系是2维的。
- 屏幕坐标系是以屏幕左下角为(0,0), 右上角 (camera.pixelWidth, camera.pixelHeight)建立的坐标系。
Input.mousePosition; // 获取鼠标在屏幕坐标系中的位置
视口坐标系
- 视口坐标系也是用来反应屏幕中位置的。
- 视口坐标系使用的是屏幕宽度和高度的百分比,其左下角(0,0),右上角 (1,1)。
- 视口坐标系适合用来在不同大小的屏幕间做适配。
GUI坐标系
- 专门用与GUI的坐标系。
- 与屏幕坐标是上下颠倒的。
- 其左上角(0,0), 右下角 (Screen.width, Screen.hight)
坐标系的转换
- GUI\屏幕间的转化
// 屏幕坐标与GUI坐标间的转化方面是一样的
Vector2 TransformScreenAndGui(Vector2 point) {
Vector2 result;
// x轴不变
result.x = point.x;
// y轴为屏幕高度减去原y坐标
result.y = Screen.hight - point.y;
return result;
}
- 屏幕\视口\世界间的转化
// 屏幕转视口
Camera.main.ScreenToViewportPoint(Input.mousePosition);
// 视口转屏幕
Camera.main.ViewportToScreenPoint(new Vector3(0.25F, 0.1F, 0));
// 屏幕转世界
// 转化后z轴不变
// 如果输入的是Vector2,转化后z轴大小为camera的z轴值
camera.ScreenToWorldPoint(Input.mousePosition);
// 世界转屏幕
camera.WorldToScreenPoint(target.transform.position);
// 视口转世界
camera.ViewportToWorldPoint(new Vector3(1, 1, camera.nearClipPlane));
// 世界转视口
camera.WorldToViewportPoint(target.transform.position);
- 物体\世界间的转化
// 物体转世界坐标
transform.TransformPoint(3, 4, 5);
// 世界转物体坐标
transform.InverseTransformPoint(3, 4, 5);
// 物体坐标系中的方向转到世界坐标方向
transform.TransformDirection(Vector3.forward);
// 世界坐标系中的方向转到物体坐标方向
transform.InverseTransformDirection(Vector3.forward);
运用举例
// 确定目标在屏幕的左边还是右边
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform target;
Camera camera;
void Start() {
camera = GetComponent<Camera>();
}
void Update() {
Vector3 viewPos = camera.WorldToViewportPoint(target.position);
if (viewPos.x > 0.5F)
print("target is on the right side!");
else
print("target is on the left side!");
}
}