欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Unity新手必知!transform.position的真实面目,你了解多少?

最编程 2024-08-06 21:59:31
...

基础知识:

Transform作为Unity中游戏对象最为重要的组件,“位置”作为Transfrom组件的一个属性,具有同等重要的地位。

Transform组件下有两个“位置”属性:

position:指的是游戏对象中心点在世界空间的位置(世界空间就是Unity最大的空间,可以创建一个无任何父节点的空对象,其position,rotation分量都是0,scale分量都是1,那么可以认为世界空间就是以此物体中心点为原点,物体的朝向为z轴,右方向为x轴,上方向为y轴,即物体的transform.forward为z轴,transform.right为x轴,transform.up为y轴,如图中的SuperParent物体)。


SuperParent1.jpg

localPosition:指的是游戏对象中心点在父类空间的位置(属性面板上显示的值就是这个值)。

父类空间的构建与其position,rotation,scale有关,但此处只讨论position,因此可以认为父类物体不旋转,没有缩放的情况。那么此时父类空间是以父类中心点为原点,x,y,z与世界空间x,y,z轴同方向。

如果游戏对象没有父类,那么此物体的父类空间就是世界空间,此时position和localPosition值是相同的。可以想象为,其父类就是文章上面的SuperParent物体。

UGUI下所有的UI空间都具有RectTransform组件,此组件继承自Transform组件,其内部的position和localPosition属性也继承自Transform。他多出来的位置属性是:

anchoredPosition3D:指的是物体中心点Pivot相对于锚点Anchor的位置(UI属性面板上显示的就是这个值,即PosX,PosY,PosZ)。

注意:

1、 这里指的是锚点,尽管锚点是附加在父类上的,但其并不是父类空间,父类空间指的是以其中心点为原点,而此处指的是以锚点为原点。

2、 RectTransform提供了我们足够的*去更改UI的锚点位置和中心点的位置。但是万变不离其宗:anchoredPosition3D核心概念没变:中心点相对锚点的位置。

3、 anchoredPosition是anchoredPosition3D属性去除了z轴之后的值。

扩展知识:

尽管上述概念都是大家耳熟能详的东西,有关的博文一搜一大堆,我为什么要再总结一篇大家都知道的东西呢?因为看似简单的东西,可以做出复杂的系统,看似复杂的东西,都是由简单的东西堆砌出来的。

重点来了:位置脱离了空间系统毫无意义。人尽皆知啊。接下来请牢记:位置计算一定要统一空间。

Unity中,游戏物体除了有本地位置,世界空间位置,还有相对摄像机的位置(视角空间位置),屏幕空间位置。其中的转换详情计算机图形学,以后我也会总结有关图形学的知识。

实战:

最后用一个例子介绍一下这些位置的用途。

王者荣耀英雄展示界面。一边为英雄模型,一边为UI显示英雄技能等信息,是怎么样做到的模型跟正好显示在了规定的地方。如图:


Hero.jpg

两个接口(Camera组件下):

    public  Vector3 WorldToScreenPoint(Vector3 position);
    //输入物体世界空间坐标得到物体当前摄像机下屏幕空间坐标位置
    public Vector3 ScreenToWorldPoint(Vector3 position);
    //输入物体当前摄像机下屏幕空间坐标得到物体世界空间坐标位置

注意:

1、屏幕空间坐标依赖于摄像机。同一物体,在不同摄像机下,其得到的屏幕坐标是不同的。不懂的话,可以了解一下图形学坐标转换。

2、屏幕空间坐标是三维的。其x,y轴是指显示在屏幕上的位置,z轴具有特殊意义——物体的深度值(与物体距离摄像机的远近有关)。

Camera组件下有很对关于空间位置的计算。有兴趣的话,可以研究研究。

首先我们需要两个摄像机:一个UI摄像机显示UI,一个模型摄像机显示模型。

具体思路:由UI位置计算其屏幕坐标位置,再由屏幕坐标位置计算模型世界空间位置。

场景:一个button,button下有一个位置标识,通过我点击button,会在该位置标识上生成一个小球(这个button同时充当了模型展台,小球就是宫本。太low了,哈哈),game场景如下:


Scene.png

代码如下:

    public GameObject prefab;           //小球预制件
    public Camera uiCamera;             //UI摄像机
    public Camera modelCamera;          //模型摄像机
    public GameObject posTag;           //需要把模型放置的位置
    public int z = 5;                   //修改屏幕坐标的Z轴
    public void ClickButton()
    {
        //初始化物体
        GameObject go = GameObject.Instantiate(prefab);
        Vector3 showPos = posTag.transform.position;
        //获取展示位置的屏幕空间坐标
        Vector3 screenPos = uiCamera.WorldToScreenPoint(showPos);
        //设置屏幕坐标的z轴。z轴代表物体的深度值,与距离摄像机的远近有关。
        //可以调一下大小感受一下
        screenPos.z = z;
        //获取模型摄像机下得到同一屏幕空间坐标的世界空间坐标
        Vector3 modelPos = modelCamera.ScreenToWorldPoint(screenPos);
        go.transform.position = modelPos;
    }

效果展示:


position.gif

位置不对啊?其实是因为所有的坐标都是以中心点为基础的。小球的中心点在圆心,所以小球的中心点是与标志物重合的。在游戏中,美术提交的模型中心点基本都会设置在人物脚上,所以就不会出现这个情况。

小结:

知识点:位置概念不能脱离空间。位置计算一定要统一空间。