zoukankan      html  css  js  c++  java
  • 关于Unity中的transform组件(二)

    在Scene视图中的蓝色网格,每一格默认是1米

    一、沿着Z轴每秒移动10米

    Transform cube_trans;

    void start(){

      this.cube_trans=this.transform.Find("cube");

    }

    void upate(){

      float s=10*Time.deltaTime;//每次移动的距离=速度*移动一次的时间间隔,距离是标量

      this.cube_trans.position=this.cube_trans.position+this.cube_trans.forward*s;//forward是单位向量,这里单位向量*变量表示在这个方向移动的距离,单位向量*变量得到的是这个标量在这个单位向量上的x,y,z的分解。

    }

    二、局部坐标和世界坐标的转换(世界坐标系就是scene视图的右上角那个坐标系)

    在unity编辑器中,默认是设置局部坐标,除了一些根节点的局部坐标和世界坐标一样的情况,如Main Camera,Directional Light,game_root等节点。

    在代码编辑器中,默认是世界坐标,即不管是父节点还是子节点,使用 this.transform.position得到的坐标,都是世界坐标。硬要获得局部坐标可以用this.transform.localPosition。

    1.将局部坐标转成世界坐标
    方法a:Vector3 w_pos = this.transform.TransformPoint(new Vector3(0, 0, 0));//其中new Vector3(0, 0, 0)是相对于当前脚本所挂载节点的三维局部坐标,w_pos则是世界坐标。

    Debug.Log(w_pos );//原先设置的this.transform.gameObject这个根节点的世界坐标为(0,0,10),所以这里的输出结果应该是(0,0,10)。

    方法b:Vector3 w_pos = this.transform.TransformVector(0, 0, 0);//其中(0, 0, 0)是相对于当前脚本所挂载节点的三维局部坐标,w_pos则是世界坐标。

     Debug.Log(w_pos );//原先设置的this.transform.gameObject这个根节点的世界坐标为(0,0,10),所以这里的输出结果应该是(0,0,10)。

    2.将世界坐标转成局部坐标

    Vector3 local_wpos = this.transform.InverseTransformPoint(new Vector3(0, 0, 15));//其中new Vector3(0, 0, 15)是三维世界坐标,local_wpos 则是局部坐标。
    Debug.Log(local_wpos);//原先设置的this.transform.gameObject这个根节点的世界坐标为(0,0,10),所以这里的输出结果应该是(0,0,5)。

    3.物体的局部坐标的方向(物体自身的方向)

    transform.forward、 transform.right、 transform.up

    4.物体的世界坐标的方向

    Vector3.forward、 Vector3.right、 Vector3.up

    三、平移,缩放

    1.Space.Self和Space.World

    点击一个节点,按住ALT+鼠标左键进行旋转节点,或者平移节点等操作,这个操作的范围就是在这个节点自己的的坐标系中,名字叫Space.Self

    如果让一个节点绕另一个节点旋转,像地球绕太阳那样旋转,那么这个操作的范围就是在世界坐标系中,名字叫Space.World

    2.平移

    void upate(){

      float s=10*Time.deltaTime;//每次移动的距离=速度*移动一次的时间间隔,距离是标量

      //情况a

      this.cube_trans.Translate(new Vector3(0,0,s));//如果没有制定坐标系,那么x,y,z就是自己节点模型的坐标系Space.Self,这时候会往节点的z轴的方向移动。

      //情况b

      this.cube_trans.Translate(new Vector3(0,0,s),Space.World);//如果指定了坐标系,那么就按照指定的坐标系的方向进行运动,比如这里就是按照世界坐标系的z轴方向移动。

      //情况c

      this.cube_trans.Translate(new Vector3(0,0,s),this.transform);//这时候设置了以某个节点的坐标系为参考系,以参考系的方向为平移方向,这里是把,this.transform也就是game_root这个根节点作为参考系,所以game_root节点的z轴在哪个方向上,                                                                                                    cube就往哪个方向平移。

    }

    3.缩放

    //情况a

    Debug.Log(this.cube_trans.localScale);//当前节点的缩放系数,不考虑父节点的影响,也就是在Unity编辑器上节点的的scale值,是一个三维的数。

    //localScale是可读可写的,从F12看函数定义可以看出,localScale有get和set访问器。

    //情况b
    Debug.Log(this.cube_trans.lossyScale);// 如果所有的父亲又缩放,那么这个比例系数,也会影响到孩子。整个这个对象在全局的缩放系数,结果是(父节点的x缩放系数*子节点的x缩放系数,父节点的y缩放系数*子节点的y缩放系数,父节点的z缩放系数*子节点的z缩放系数)。

    //lossyScale是只能读的,从F12看函数定义可以看出,lossyScale只有get访问器。

    四、旋转

    相比平移和缩放,比较复杂。

    如果用数学矩阵表示任意的旋转,虽然是可行的,但是每个矩阵需要16个数,很消耗内存。其实旋转只要旋转方向向量(x,y,z)旋转角度4个数就可以了,没必要用到16个数。

    1.使用欧拉角表示:

    一个节点先绕自身x轴旋转一定角度,再绕自身y轴旋转一定角度,最后绕自身z轴旋转一定角度,最后的结果构成欧拉角。

    不同的轴旋转顺序,会得到不同的结果。Unity规定是按照zxy的旋转顺序来决定欧拉角的,不管我们怎么填旋转角度都是用那个顺序绘制的。

    所以Unity的inspector视图上的

    Rotaton x 12 y 24 z 48表示,先绕z轴旋转48度,再绕x轴旋转12度,最后绕y轴旋转24度。

    缺点:会造成万向节锁的现象。

    2.使用四元数Quaternion表示:

    节点在一个方向旋转多少角度

      Debug.Log(this.cube_trans.rotation);

    优点:

    (1)可以避免万向节锁现象;
    (2)只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高
    (3)可以提供平滑插值;

    缺点:

    比欧拉旋转稍微复杂了一点点,因为多了一个维度。

    3.四元数和欧拉角互相转换

    欧拉角和四元数可以相互转换。Unity的编辑器使用的是欧拉角,代码编译器使用的是四元数,所以打印出来的Unity编辑器和代码中的x,y,z的值会不一样。

    // unity transform里面为了避免万象节锁,使用的是四元数来存放一个旋转;
    // unity编辑器里面为了直观的来旋转,使用的是欧拉角来表示

    (1)四元数转欧拉角
    Vector3 e_degree = this.cube_trans.rotation.eulerAngles;//e_degree是欧拉角,this.cube_trans.rotation是四元数
    Debug.Log(e_degree);

    虽然转换出来的e_degree和Unity编辑器上Inspector面板上的Rotation的值还是有一些区别,主要是因为四舍五入和一些运算造成的差值,这些差值基本没影响。

    (2)欧拉角转四元数

    //绕y周旋转45;

    // this.cube_trans.rotation = Quaternion.Euler(new Vector3(0, 45, 0));//里面的new Vector3(0, 45, 0)是欧拉角,this.cube_trans.rotation是四元数

    (3)使用欧拉角做旋转操作
    // 欧拉角旋转, 在当前的基础,再绕y周旋转45;
    this.cube_trans.Rotate(new Vector3(0, 45, 0));

    (4)使用四元数做旋转叠加

    void update(){

      float w = 360;
      float degree = w * Time.deltaTime;
      // this.cube_trans.Rotate(0, degree, 0);//这个语句是每一帧旋转360度,这个貌似是用欧拉角旋转的。

      this.cube_trans.rotation = this.cube_trans.rotation * Quaternion.Euler(new Vector3(0, degree, 0));//把每个小变换组成一个大的总的变换,那么是用 * 和矩阵类似,这个是用四元数的叠加的。

    }

  • 相关阅读:
    博客园转文章的方法
    http协议相关面试题
    接口测试基础01
    文件上传下载
    括号-回溯
    幂集-回溯
    分割数组为连续子序列- -贪心法
    不使用临时变量交换数字
    计数质数
    拼接最大值
  • 原文地址:https://www.cnblogs.com/HangZhe/p/6825693.html
Copyright © 2011-2022 走看看