Unity3D的几种坐标系

来源:互联网 发布:mac numbers 使用技巧 编辑:程序博客网 时间:2024/04/30 13:52


  1. World Space(世界坐标):我们在场景中添加物体(如:Cube),他们都是以世界坐标显示在场景中的。transform.position可以获得该位置坐标。            
  2. Screen Space(屏幕坐标,鼠标坐标):以像素来定义的,以屏幕的左下角为(0,0)点,右上角为(Screen.width,Screen.height),Z的位置是以相机的世界单位来衡量的。注:鼠标位置坐标属于屏幕坐标,Input.mousePosition可以获得该位置坐标,手指触摸屏幕也为屏幕坐标,Input.GetTouch(0).position可以获得单个手指触摸屏幕坐标。

  3. ViewPort Space(视口坐标):视口坐标是标准的和相对于相机的。相机的左下角为(0,0)点,右上角为(1,1)点,Z的位置是以相机的世界单位来衡量的。(用的不多,反正我暂时没有用到~呵呵~)

  4. 绘制GUI界面的坐标系:这个坐标系与屏幕坐标系相似,不同的是该坐标系以屏幕的左上角为(0,0)点,右下角为(Screen.width,Screen.height)。

  5. LineRender坐标:以屏幕中心为原点,向上向右增加。
  • 世界坐标→屏幕坐标:camera.WorldToScreenPoint(transform.position);这样可以将世界坐标换为屏幕坐标。其中camera为场景中的camera对象。

  • 屏幕坐标→视口坐标:camera.ScreenToViewportPoint(Input.GetTouch(0).position);这样可以将屏幕坐标换为视口坐标。其中camera为场景中的camera对象。

  • 视口坐标→屏幕坐标:camera.ViewportToScreenPoint();

  • 视口坐标→世界坐标:camera.ViewportToWorldPoint();

案例1——在鼠标点击的位置上绘制一张图片出来(关于绘制GUI界面坐标系与屏幕坐标系之间的关系)。

using UnityEngine;using System.Collections;public class ScreenToGUI : MonoBehaviour {    // Use this for initialization    void Start () {        }        // Update is called once per frame    void Update () {        }        //图片      public Texture img;         //储存鼠标的位置坐标        private Vector2 pos;    void OnGUI()    {        //鼠标左击,获取当前鼠标的位置               if (Input.GetMouseButton(0))        {            pos = Input.mousePosition; //屏幕坐标        }        //绘制图片,屏幕坐标和GUI界面坐标只在Y轴上方向相反,只要被Screen.height减就可以互相换。              GUI.DrawTexture(new Rect(pos.x, Screen.height - pos.y, 100, 100), img);    }}

案例2——角色头顶的名字(世界坐标转GUI界面坐标)

先世界坐标屏幕坐标,再屏幕坐标转GUI界面坐标

代码如下:

using UnityEngine;using System.Collections;public class Blood : MonoBehaviour {    public static float ScaleWidht = 0f;    public static float ScaleHeight = 0f;    private Rect _drawRect = new Rect();    public float Width = 0f;    public float Height = 10f;    public const float DesignStageWidth = 800;    public const float DesignStageHeight = 480;    public Vector2 pos2;    public float size_z;    // Use this for initialization    void Start () {        ScaleWidht = Screen.width / DesignStageWidth;        ScaleHeight = Screen.height / DesignStageHeight;        Height = 2f;        size_z = transform.gameObject.collider.bounds.size.z;    }    // Update is called once per frame    void Update () {        //世界坐标换到屏幕坐标        print(transform.forward);        pos2 = Camera.main.WorldToScreenPoint(transform.position + transform.forward * (size_z / 2));         //计算角色头顶坐标        pos2 = new Vector2(pos2.x, Screen.height  - pos2.y - Height);         //Vector3 worldPosition = new Vector3(transform.position.x, transform.position.y + Height, transform.position.z);        //worldPosition = Camera.mainCamera.WorldToScreenPoint(worldPosition);        //_drawRect = new Rect((worldPosition.x - 100 * ScaleWidht) / ScaleWidht, (Screen.height - worldPosition.y - 50 * ScaleHeight) / ScaleHeight, 200, 50);    }    void OnGUI()    {        //GUILayout.BeginArea(_drawRect);        //    GUILayout.Label("======哈哈======");        //GUILayout.EndArea();        GUI.Label(new Rect(pos2.x, pos2.y, 100, 50), "=BETTER=");    }}

 案例3——类似屏幕解锁功能的实现(屏幕坐标换为世界坐标)

首先是创建LineRenderer。GameObject -> Create Empty ->更名为“LineRendererObj”,

给LineRendererObj添加“Line Renderer”组件,Component ->Effects ->Line Renderer;

将它的Positions 的size 设置为0

接下来是代码touch.CS:

using UnityEngine;using System.Collections;using System.Collections.Generic;public class touch : MonoBehaviour {    private Event e;    public Texture2D Point;    public Color c1 = Color.yellow;    public Color c2 = Color.red;    public int lengthOfLineRenderer;    public GameObject LineRendererPrefab;    private LineRenderer lineRenderer;    /// <summary>    /// 保存创建的Line Renderer    /// </summary>    private List<LineRenderer> lineRendArray =new List<LineRenderer>();    private Vector3 screenPoint;    private Vector3 scanPos;    private Color[] color;    /// <summary>    /// 记录宫格所在GUI位置    /// </summary>    public List<Rect> AreaRect = new List<Rect>();    /// <summary>    /// 记录宫格中心点    /// </summary>    public List<Vector2> CenterPointList = new List<Vector2>();    /// <summary>    /// 宫格标签    /// </summary>    public int RectFlag;    /// <summary>    /// 记录正确的滑动顺序    /// </summary>    public List<int> KeyOrder = new List<int>();    /// <summary>    /// 记录玩家滑动顺序    /// </summary>    public List<int> PlayerKeyOrder = new List<int>();    /// <summary>    /// 判断开始鼠标位置是否可画    /// </summary>    public bool CheckStartRect=false;    /// <summary>    /// 判断结束鼠标位置是否可画    /// </summary>    public bool CheckEndRect = false;    /// <summary>    /// 行数    /// </summary>    public int Row = 4;    /// <summary>    /// 列数    /// </summary>    public int Column = 4;    void Start()    {        e = Event.current;        scanPos = LineRendererPrefab.transform.position;        lineRenderer = (LineRenderer)LineRendererPrefab.GetComponent("LineRenderer");        lineRenderer.material = new Material(Shader.Find("Particles/Additive"));        lengthOfLineRenderer = 0;        lineRenderer.SetColors(c1, c2);        lineRenderer.SetWidth(0.7F, 0.7F);        lineRenderer.SetVertexCount(0);        color = new Color[8];        color[0] = Color.yellow;        color[1] = Color.blue;        color[2] = Color.cyan;        color[3] = Color.gray;        color[4] = Color.green;        color[5] = Color.grey;        color[6] = Color.magenta;        color[7] = Color.red;        for (int RowCount = 0; RowCount < Row; RowCount++)        {            for (int columnCount = 0; columnCount < Column; columnCount++)            {                Rect IconRect = new Rect(columnCount * Screen.width / Column + Screen.width / Column / 2 - Point.width / 2, RowCount * Screen.height / Row + Screen.height / Row / 2 - Point.height / 2, Point.width, Point.height);                AreaRect.Add(IconRect);                Vector2 CenterP = IconRect.center;//得到每个的中心点                CenterPointList.Add(CenterP);            }        }    }    void OnGUI()    {        e = Event.current;        for (int RowCount = 0; RowCount < Row; RowCount++)        {            for (int columnCount = 0; columnCount < Column; columnCount++)            {                Rect IconRect = new Rect(columnCount * Screen.width / Column + Screen.width / Column / 2 - Point.width / 2, RowCount * Screen.height / Row + Screen.height / Row / 2 - Point.height / 2, Point.width, Point.height);                GUI.Label(IconRect, Point);            }        }    }    void Update()    {        if (e != null)        {            if (e.type == EventType.MouseDown)            {                for (int i = 0; i < AreaRect.Count; i++)                {                    if (AreaRect[i].Contains(new Vector3(Input.mousePosition.x, Screen.height - Input.mousePosition.y, Input.mousePosition.z)))                    {                        CheckStartRect = true;                        print("Contains");                        PlayerKeyOrder.Add(i);                        RectFlag = i;                        break;                    }                    else                    {                        CheckStartRect = false;                    }                }                if (CheckStartRect)                {                    print("MouseDown_____");                    //Vector3 curPosition = mousePToLineRendererP();                     Vector3 curPosition = centerPToLineRendererP(RectFlag);                    GameObject newObj;                    newObj = (GameObject)Instantiate(LineRendererPrefab, LineRendererPrefab.transform.position, LineRendererPrefab.transform.rotation);                    lineRenderer = (LineRenderer)newObj.GetComponent("LineRenderer");                    int n = Random.Range(1, 8);                    c1 = color[n - 1];                    n = Random.Range(1, 8);                    c2 = color[n - 1];                    lineRenderer.SetColors(c1, c2);                    lineRenderer.SetVertexCount(1);                    lineRenderer.SetWidth(0.7F, 0.7F);                    lineRenderer.SetPosition(0, curPosition);                    lineRendArray.Add(lineRenderer);                    lengthOfLineRenderer++;                }            }            if (e.type == EventType.MouseDrag&&CheckStartRect)            {                print("MouseDrag_____");                Vector3 curPosition = mousePToLineRendererP();                 DrawRenderLine(lineRendArray[lengthOfLineRenderer - 1], curPosition);            }            if (e.type == EventType.MouseUp && CheckStartRect)            {                for (int i = 0; i < AreaRect.Count; i++)                {                    if (AreaRect[i].Contains(new Vector3(Input.mousePosition.x, Screen.height - Input.mousePosition.y, Input.mousePosition.z)))                    {                        CheckEndRect = true;                        PlayerKeyOrder.Add(i);                        RectFlag = i;                        print("EndContains");                        break;                    }                    else                    {                        CheckEndRect = false;                    }                }                if (CheckEndRect)                {                    Vector3 curPosition = centerPToLineRendererP(RectFlag);                    DrawRenderLine(lineRendArray[lengthOfLineRenderer - 1], curPosition);                }                else                {                    PlayerKeyOrder.RemoveAt(PlayerKeyOrder.Count - 1);                    Destroy(lineRendArray[lengthOfLineRenderer - 1].gameObject);                    //lengthOfLineRenderer--;                }            }        }            }    void DrawRenderLine(LineRenderer line, Vector3 vect3)    {        Vector3 newPos = vect3;        line.SetVertexCount(2);        line.SetPosition(1, newPos);        print("new point: " + newPos);    }    //public Vector2 RectCenterPoint(Rect AreaRect)       //计算一个Rect的中心点    //{    //    Vector2 CenterPoint=Vector2.zero;    //    print("Rect:"+AreaRect);    //    CenterPoint.x=AreaRect.xMin+AreaRect.width/2;            //    CenterPoint.y=AreaRect.yMin+AreaRect.height/2;    //    print("CenterPoint:"+CenterPoint);    //    return CenterPoint;    //}    /// <summary>    /// 鼠标所在位置换为LineRenderer的位置    /// </summary>    /// <returns></returns>    public Vector3 mousePToLineRendererP()          {        screenPoint = Camera.main.WorldToScreenPoint(scanPos);        Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);        Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint);        print("curScreenPoint: " + curScreenPoint);        print("curPosition: " + curPosition);        return curPosition;    }    /// <summary>    /// 鼠标所在区域的中心点换为LineRenderer的位置    /// </summary>    /// <returns></returns>    public Vector3 centerPToLineRendererP(int Flag)    {        screenPoint = Camera.main.WorldToScreenPoint(scanPos);        Vector3 curScreenPoint = new Vector3(CenterPointList[Flag].x,Screen.height-CenterPointList[Flag].y,screenPoint.z);        Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint);        print("curScreenPoint: " + curScreenPoint);        print("curPosition: " + curPosition);        return curPosition;    }}

把touch.CS绑定在Camera上,设置如下:

 运行后可以任意点间连线,如图:

 

  1. World Space(世界坐标):我们在场景中添加物体(如:Cube),他们都是以世界坐标显示在场景中的。transform.position可以获得该位置坐标。            
  2. Screen Space(屏幕坐标,鼠标坐标):以像素来定义的,以屏幕的左下角为(0,0)点,右上角为(Screen.width,Screen.height),Z的位置是以相机的世界单位来衡量的。注:鼠标位置坐标属于屏幕坐标,Input.mousePosition可以获得该位置坐标,手指触摸屏幕也为屏幕坐标,Input.GetTouch(0).position可以获得单个手指触摸屏幕坐标。

  3. ViewPort Space(视口坐标):视口坐标是标准的和相对于相机的。相机的左下角为(0,0)点,右上角为(1,1)点,Z的位置是以相机的世界单位来衡量的。(用的不多,反正我暂时没有用到~呵呵~)

  4. 绘制GUI界面的坐标系:这个坐标系与屏幕坐标系相似,不同的是该坐标系以屏幕的左上角为(0,0)点,右下角为(Screen.width,Screen.height)。

  5. LineRender坐标:以屏幕中心为原点,向上向右增加。
  • 世界坐标→屏幕坐标:camera.WorldToScreenPoint(transform.position);这样可以将世界坐标换为屏幕坐标。其中camera为场景中的camera对象。

  • 屏幕坐标→视口坐标:camera.ScreenToViewportPoint(Input.GetTouch(0).position);这样可以将屏幕坐标换为视口坐标。其中camera为场景中的camera对象。

  • 视口坐标→屏幕坐标:camera.ViewportToScreenPoint();

  • 视口坐标→世界坐标:camera.ViewportToWorldPoint();

案例1——在鼠标点击的位置上绘制一张图片出来(关于绘制GUI界面坐标系与屏幕坐标系之间的关系)。

using UnityEngine;using System.Collections;public class ScreenToGUI : MonoBehaviour {    // Use this for initialization    void Start () {        }        // Update is called once per frame    void Update () {        }        //图片      public Texture img;         //储存鼠标的位置坐标        private Vector2 pos;    void OnGUI()    {        //鼠标左击,获取当前鼠标的位置               if (Input.GetMouseButton(0))        {            pos = Input.mousePosition; //屏幕坐标        }        //绘制图片,屏幕坐标和GUI界面坐标只在Y轴上方向相反,只要被Screen.height减就可以互相换。              GUI.DrawTexture(new Rect(pos.x, Screen.height - pos.y, 100, 100), img);    }}

案例2——角色头顶的名字(世界坐标转GUI界面坐标)

先世界坐标屏幕坐标,再屏幕坐标转GUI界面坐标

代码如下:

using UnityEngine;using System.Collections;public class Blood : MonoBehaviour {    public static float ScaleWidht = 0f;    public static float ScaleHeight = 0f;    private Rect _drawRect = new Rect();    public float Width = 0f;    public float Height = 10f;    public const float DesignStageWidth = 800;    public const float DesignStageHeight = 480;    public Vector2 pos2;    public float size_z;    // Use this for initialization    void Start () {        ScaleWidht = Screen.width / DesignStageWidth;        ScaleHeight = Screen.height / DesignStageHeight;        Height = 2f;        size_z = transform.gameObject.collider.bounds.size.z;    }    // Update is called once per frame    void Update () {        //世界坐标换到屏幕坐标        print(transform.forward);        pos2 = Camera.main.WorldToScreenPoint(transform.position + transform.forward * (size_z / 2));         //计算角色头顶坐标        pos2 = new Vector2(pos2.x, Screen.height  - pos2.y - Height);         //Vector3 worldPosition = new Vector3(transform.position.x, transform.position.y + Height, transform.position.z);        //worldPosition = Camera.mainCamera.WorldToScreenPoint(worldPosition);        //_drawRect = new Rect((worldPosition.x - 100 * ScaleWidht) / ScaleWidht, (Screen.height - worldPosition.y - 50 * ScaleHeight) / ScaleHeight, 200, 50);    }    void OnGUI()    {        //GUILayout.BeginArea(_drawRect);        //    GUILayout.Label("======哈哈======");        //GUILayout.EndArea();        GUI.Label(new Rect(pos2.x, pos2.y, 100, 50), "=BETTER=");    }}

 案例3——类似屏幕解锁功能的实现(屏幕坐标换为世界坐标)

首先是创建LineRenderer。GameObject -> Create Empty ->更名为“LineRendererObj”,

给LineRendererObj添加“Line Renderer”组件,Component ->Effects ->Line Renderer;

将它的Positions 的size 设置为0

接下来是代码touch.CS:

using UnityEngine;using System.Collections;using System.Collections.Generic;public class touch : MonoBehaviour {    private Event e;    public Texture2D Point;    public Color c1 = Color.yellow;    public Color c2 = Color.red;    public int lengthOfLineRenderer;    public GameObject LineRendererPrefab;    private LineRenderer lineRenderer;    /// <summary>    /// 保存创建的Line Renderer    /// </summary>    private List<LineRenderer> lineRendArray =new List<LineRenderer>();    private Vector3 screenPoint;    private Vector3 scanPos;    private Color[] color;    /// <summary>    /// 记录宫格所在GUI位置    /// </summary>    public List<Rect> AreaRect = new List<Rect>();    /// <summary>    /// 记录宫格中心点    /// </summary>    public List<Vector2> CenterPointList = new List<Vector2>();    /// <summary>    /// 宫格标签    /// </summary>    public int RectFlag;    /// <summary>    /// 记录正确的滑动顺序    /// </summary>    public List<int> KeyOrder = new List<int>();    /// <summary>    /// 记录玩家滑动顺序    /// </summary>    public List<int> PlayerKeyOrder = new List<int>();    /// <summary>    /// 判断开始鼠标位置是否可画    /// </summary>    public bool CheckStartRect=false;    /// <summary>    /// 判断结束鼠标位置是否可画    /// </summary>    public bool CheckEndRect = false;    /// <summary>    /// 行数    /// </summary>    public int Row = 4;    /// <summary>    /// 列数    /// </summary>    public int Column = 4;    void Start()    {        e = Event.current;        scanPos = LineRendererPrefab.transform.position;        lineRenderer = (LineRenderer)LineRendererPrefab.GetComponent("LineRenderer");        lineRenderer.material = new Material(Shader.Find("Particles/Additive"));        lengthOfLineRenderer = 0;        lineRenderer.SetColors(c1, c2);        lineRenderer.SetWidth(0.7F, 0.7F);        lineRenderer.SetVertexCount(0);        color = new Color[8];        color[0] = Color.yellow;        color[1] = Color.blue;        color[2] = Color.cyan;        color[3] = Color.gray;        color[4] = Color.green;        color[5] = Color.grey;        color[6] = Color.magenta;        color[7] = Color.red;        for (int RowCount = 0; RowCount < Row; RowCount++)        {            for (int columnCount = 0; columnCount < Column; columnCount++)            {                Rect IconRect = new Rect(columnCount * Screen.width / Column + Screen.width / Column / 2 - Point.width / 2, RowCount * Screen.height / Row + Screen.height / Row / 2 - Point.height / 2, Point.width, Point.height);                AreaRect.Add(IconRect);                Vector2 CenterP = IconRect.center;//得到每个的中心点                CenterPointList.Add(CenterP);            }        }    }    void OnGUI()    {        e = Event.current;        for (int RowCount = 0; RowCount < Row; RowCount++)        {            for (int columnCount = 0; columnCount < Column; columnCount++)            {                Rect IconRect = new Rect(columnCount * Screen.width / Column + Screen.width / Column / 2 - Point.width / 2, RowCount * Screen.height / Row + Screen.height / Row / 2 - Point.height / 2, Point.width, Point.height);                GUI.Label(IconRect, Point);            }        }    }    void Update()    {        if (e != null)        {            if (e.type == EventType.MouseDown)            {                for (int i = 0; i < AreaRect.Count; i++)                {                    if (AreaRect[i].Contains(new Vector3(Input.mousePosition.x, Screen.height - Input.mousePosition.y, Input.mousePosition.z)))                    {                        CheckStartRect = true;                        print("Contains");                        PlayerKeyOrder.Add(i);                        RectFlag = i;                        break;                    }                    else                    {                        CheckStartRect = false;                    }                }                if (CheckStartRect)                {                    print("MouseDown_____");                    //Vector3 curPosition = mousePToLineRendererP();                     Vector3 curPosition = centerPToLineRendererP(RectFlag);                    GameObject newObj;                    newObj = (GameObject)Instantiate(LineRendererPrefab, LineRendererPrefab.transform.position, LineRendererPrefab.transform.rotation);                    lineRenderer = (LineRenderer)newObj.GetComponent("LineRenderer");                    int n = Random.Range(1, 8);                    c1 = color[n - 1];                    n = Random.Range(1, 8);                    c2 = color[n - 1];                    lineRenderer.SetColors(c1, c2);                    lineRenderer.SetVertexCount(1);                    lineRenderer.SetWidth(0.7F, 0.7F);                    lineRenderer.SetPosition(0, curPosition);                    lineRendArray.Add(lineRenderer);                    lengthOfLineRenderer++;                }            }            if (e.type == EventType.MouseDrag&&CheckStartRect)            {                print("MouseDrag_____");                Vector3 curPosition = mousePToLineRendererP();                 DrawRenderLine(lineRendArray[lengthOfLineRenderer - 1], curPosition);            }            if (e.type == EventType.MouseUp && CheckStartRect)            {                for (int i = 0; i < AreaRect.Count; i++)                {                    if (AreaRect[i].Contains(new Vector3(Input.mousePosition.x, Screen.height - Input.mousePosition.y, Input.mousePosition.z)))                    {                        CheckEndRect = true;                        PlayerKeyOrder.Add(i);                        RectFlag = i;                        print("EndContains");                        break;                    }                    else                    {                        CheckEndRect = false;                    }                }                if (CheckEndRect)                {                    Vector3 curPosition = centerPToLineRendererP(RectFlag);                    DrawRenderLine(lineRendArray[lengthOfLineRenderer - 1], curPosition);                }                else                {                    PlayerKeyOrder.RemoveAt(PlayerKeyOrder.Count - 1);                    Destroy(lineRendArray[lengthOfLineRenderer - 1].gameObject);                    //lengthOfLineRenderer--;                }            }        }            }    void DrawRenderLine(LineRenderer line, Vector3 vect3)    {        Vector3 newPos = vect3;        line.SetVertexCount(2);        line.SetPosition(1, newPos);        print("new point: " + newPos);    }    //public Vector2 RectCenterPoint(Rect AreaRect)       //计算一个Rect的中心点    //{    //    Vector2 CenterPoint=Vector2.zero;    //    print("Rect:"+AreaRect);    //    CenterPoint.x=AreaRect.xMin+AreaRect.width/2;            //    CenterPoint.y=AreaRect.yMin+AreaRect.height/2;    //    print("CenterPoint:"+CenterPoint);    //    return CenterPoint;    //}    /// <summary>    /// 鼠标所在位置换为LineRenderer的位置    /// </summary>    /// <returns></returns>    public Vector3 mousePToLineRendererP()          {        screenPoint = Camera.main.WorldToScreenPoint(scanPos);        Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);        Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint);        print("curScreenPoint: " + curScreenPoint);        print("curPosition: " + curPosition);        return curPosition;    }    /// <summary>    /// 鼠标所在区域的中心点换为LineRenderer的位置    /// </summary>    /// <returns></returns>    public Vector3 centerPToLineRendererP(int Flag)    {        screenPoint = Camera.main.WorldToScreenPoint(scanPos);        Vector3 curScreenPoint = new Vector3(CenterPointList[Flag].x,Screen.height-CenterPointList[Flag].y,screenPoint.z);        Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint);        print("curScreenPoint: " + curScreenPoint);        print("curPosition: " + curPosition);        return curPosition;    }}

把touch.CS绑定在Camera上,设置如下:

 运行后可以任意点间连线,如图:

 

0 0