zoukankan      html  css  js  c++  java
  • Unity中坐标系转换方法

    前言

    本篇文章主要是参考《Unity API 解析》---陈泉宏。

    这是本人在学校图书馆找到一本书,主要介绍的就是常用的类,比较实用,没有冗余的地方。在此推荐一下这本书!

    一、ScreenToViewportPoint方法

    1、函数原型

    public Vector3 ScreenToViewportPoint(Vector3 position);

    其中参数position为屏幕参考点。

    2、功能说明

    可以实现坐标点position从屏幕坐标系向摄像机视口的单位化坐标系转换。参考点position的x和y分量为屏幕的实际坐标值,单位为像素,z值无效。

    3、实例演示

    using UnityEngine;
    using System.Collections;
    
    public class ScreenToViewportPoint_ts : MonoBehaviour {
    
    
        // Use this for initialization
        void Start () {
    
            transform.position = new Vector3(0.0f, 0.0f, 1.0f);
            transform.rotation = Quaternion.identity;
            //从屏幕的实际坐标向视口的单位化比例值转换
            Vector3 viewPortPoint = camera.ScreenToViewportPoint(new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 100.0f));
            Debug.Log("转换后的摄像机视口坐标系的坐标: " + viewPortPoint);
            //从视口的单位化比例值向屏幕的实际坐标点转换
            Vector3 screenPoint = camera.ViewportToScreenPoint(viewPortPoint);
            Debug.Log("转换后的屏幕坐标: " + screenPoint);
            Debug.Log("屏幕宽: " + Screen.width + " 屏幕高: " + Screen.height);
    
    
        }
    
        // Update is called once per frame
        void Update () {
        
        }
    }

     4、运行结果

    二、ScreenToWorldPoint方法

    1、函数原型

    public Vector3 ScreenToWorldPoint(Vector3 position);//position是参考点

    2、功能说明

    将参考点position从屏幕坐标系转换到世界坐标系。position中各个分量值都为实际单位像素值,而非比例值。

    Vector3 v = camera.ScreenToWorldPoint(ps);//ps为参考点
    //v的各个分量值为
    v.x = camera.transform.position.x + ps.z*asp*tan(e/2);
    v.y = camera.transform.position.y + ps.z*tan(e/2);
    v.z = camera.transform.position.z + ps.z;

    其中e为摄像机的视口夹角fieldOfView的值,asp为摄像机视口的宽高比例值aspect。具体了解可以参考3D游戏与计算机图形学中的数学方法-视截体

    3、实例演示

    using UnityEngine;
    using System.Collections;
    
    public class ScreenToWorldPoint_ts : MonoBehaviour
    {
    
    
        // Use this for initialization
        void Start () {
    
            transform.position = new Vector3(0.0f, 0.0f, 1.0f);
            camera.fieldOfView = 60.0f;
            camera.aspect = 1.6f;
            Debug.Log("z轴正方向100单位处对应的屏幕左下角的世界坐标值: " + camera.ScreenToWorldPoint(new Vector3(0.0f,0.0f,100.0f)));
            Debug.Log("z轴正方向100单位处对应的屏幕中间的世界坐标值: " + camera.ScreenToWorldPoint(new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 100.0f)));
            Debug.Log("z轴正方向100单位处对应的屏幕右上角的世界坐标值: " + camera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 100.0f)));
    
        }
    
        // Update is called once per frame
        void Update () {
        
        }
    }

    4、运行结果

    三、ViewportToWorldPoint方法

    1、函数原型

    public Vector3 ViewportToWorldPoint(Vector3 position);

    2、功能说明

    可以实现从Camera视口坐标点到世界坐标点转换,与WorldToViewportPoint的功能正好相反。此方法的返回值大小受当前Camera在世界坐标系中的位置、fieldOfVieew值以及参考点position的共同影响。其中参考点position的x和y分量的有效范围为[0.0,1.0],位比例值;而z值为实际单位值,而非比例值。

    视口坐标点与世界坐标点的转换公式:

    假设ps是视口坐标点,v是转换后对应ps的世界坐标点。那么有如下方程式:

    v.x = camera.transform.position.x + K1;
    v.y = camera.transform.position.y + K2;
    v.z = camera.transform.position.z + ps.z;
    其中K1 = ps.z * asp * ((ps.x -0.5)/0.5)*tan(e/2);
    K2 = ps.z * ((ps.y -0.5)/0.5)*tan(e/2);
    e位摄像机的视口夹角fieldOfView的值,asp为摄像机视口的宽高比aspect。

    3、实例演示

    using UnityEngine;
    using System.Collections;
    
    public class ViewportToWorldPoint_ts : MonoBehaviour {
    
        // Use this for initialization
        void Start () {
    
            transform.position = new Vector3(1.0f, 0.0f, 1.0f);
            camera.fieldOfView = 60.0f;
            camera.aspect = 16.0f / 10.0f;
            Debug.Log("屏幕左下角: " + camera.ViewportToWorldPoint(new Vector3(0.0f, 0.0f, 100.0f)));
            Debug.Log("屏幕中间: " + camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 100.0f)));
            Debug.Log("屏幕右上角: " + camera.ViewportToWorldPoint(new Vector3(1.0f, 1.0f, 100.0f)));
    
        }
        
        // Update is called once per frame
        void Update () {
        
        }
    }

    4、运行结果

    其余还有WorldToScreenPoint、WorldToViewportPoint等方法,使用如上面的例子类似,在此就不做阐述了。

    四、关于Camera视口、aspect、pixelRect及Rect的解释

    • Camera视口用来记录当前摄像机能看到场景中的哪些内容,其大小及位置是可以改变的。而屏幕视口是指当前的硬件的屏幕,对于一个固定的硬件,它的屏幕视口大小(即分辨率)是固定的。Camera视口的内容不一定可以完全显示在屏幕上,屏幕可能只显示了一部分视口内容,也可能对视口内容进行了放缩。可以简单的理解为Camera视口是一张二维图片,而屏幕是用来显示这张图片的,图片可以被剪切,也可能被压缩。
    • Unity的Game面板中的aspect选项是用来模拟硬件屏幕的,可以分为三类即全屏显示、固定比例显示和固定分辨率显示。全屏显示即以当前Camera屏幕的大小来模拟硬件屏幕分辨率,其Camera视口即为当前摄像机的默认状态。而在固定比例方式则会改变Camera视口的宽高比,其大小不固定。而在固定分辨率方式下,其有效显示区间将保持固定分辨率的大小。

    Camera屏幕分辨率的设置方式

    • 在Camera.aspect固定的情况下,无论选择Game视图中哪种屏幕模拟方式,它们的显示内容都是相同的。不同的屏幕模拟方式只会对显示的内容进行放缩。决定屏幕视口显示内容的是Camera.aspect的值和Camera.transform的属性,至于屏幕要如何显示Camera视口的内容,那就是硬件显示屏要处理的事情了。
    • PixelRect和Rect功能类似,都是决定硬件显示屏如何显示Camera视口提供的内容的。不同的是PixelRect是以实际像素来展示显示内容,而Rect是以单位化形式展示显示内容。
  • 相关阅读:
    DHTML【11】--DOM
    sql 查询强制使用HASH连接性能测试比较
    Winform开发框架之读卡器和条码扫描枪的数据接收处理
    DevExpress的XtraReport和微软RDLC报表的使用和对比
    sql server日期时间转字符串
    C#在线更新程序[下载程序、解压缩程序、控制台程序]
    C# 定时器事件(设置时间间隔,间歇性执行某一函数,控制台程序)
    用C#用C#实现窗体在规定时间弹出,例如:10:00.弹出后关闭。并在5分钟后再次弹出。5次后停止。最好有具体代码实现窗体在规定时间弹出,例如:10:00.弹出后关闭。并在5分钟后再次弹出。5次后停止。最好有具体代码
    C#多线程学习之(五)使用定时器进行多线程的自动管理
    C# 文件与目录的基本操作(System.IO)
  • 原文地址:https://www.cnblogs.com/tgycoder/p/5086121.html
Copyright © 2011-2022 走看看