16.Transform变换组件位置和位移

16.Unity重要组件和API-Transform位置和位移


16.1 知识点

Transform主要用来干嘛

Transform 主要用于游戏对象(GameObject)的位移、旋转、缩放、父子关系、坐标转换等相关操作。它是 Unity 提供的极其重要的类。

Vector3三维向量基础

Vector3 主要用来表示三维坐标系中的一个点或者一个向量,用于表示 3D 向量和点。Unity 内部使用该结构传递 3D 位置和方向。此外,它还包含用于执行常见向量操作的函数。除了下面列出的函数以外,也可以使用其他类操作向量和点。例如,对于旋转或变换向量和点来说,Quaternion 和 Matrix4x4 类也很有用。

Vector3的申明

  • 无参构造后赋值:
Vector3 v1 = new Vector3();
v1.x = 10;
v1.y = 10;
v1.z = 10;
  • 传xy坐标参数的构造,默认z是0:
Vector3 v2 = new Vector3(10, 10);
  • 传xyz坐标参数的参数构造,一步到位:
Vector3 v3 = new Vector3(10, 10, 10);
  • 结构体直接声明 Vector3 变量后赋值:
Vector3 v4;
v4.x = 10;
v4.y = 10;
v4.z = 10;

Vector的基本计算

// + - * / 加减乘除
Vector3 v11 = new Vector3(1, 1, 1);
Vector3 v12 = new Vector3(2, 2, 2);
print(v11 + v12); // (3.0, 3.0, 3.0)
print(v11 - v12); // (-1.0, -1.0, -1.0)
print(v11 * 10); // (10.0, 10.0, 10.0)
print(v12 / 2); // (1.0, 1.0, 1.0)

Vector3常用的向量供我们使用

print(Vector3.zero); // (0, 0, 0)
print(Vector3.right); // (1, 0, 0)
print(Vector3.left); // (-1, 0, 0)
print(Vector3.up); // (0, 1, 0)
print(Vector3.down); // (0, -1, 0)
print(Vector3.forward); // (0, 0, 1)
print(Vector3.back); // (0, 0, -1)

Vector3.Distance方法 返回向量之间的距离

// 返回 a 与 b 之间的距离。
print(Vector3.Distance(v11, v12)); // 1.732051

位置

Vector3.position变量 相对世界坐标系的坐标

// 世界空间中的变换位置。
print(this.transform.position);
// 通过 position 得到的位置是相对于世界坐标系的原点的位置。可能和面板上显示的是不一样的,因为如果对象有父子关系,并且父对象位置不在原点,那么和面板上肯定就是不一样的。

Vector3.localPosition变量 相对父对象的坐标

// 相对于父变换的变换位置。
print(this.transform.localPosition);
// 这两个坐标对于我们来说很重要。如果你想以面板坐标为准来进行位置设置,那一定是通过 localPosition 来进行设置的。

position和localPosition值相等的情况:

  • 父对象的坐标就是世界坐标系原点(0, 0, 0)。
  • 对象没有父对象。

注意:坐标的赋值不能直接改变 x,y,z,只能整体改变。

// 不能单独改变 x、y、z 某一个值
// this.transform.position.x = 10; // 报错
this.transform.position = new Vector3(10, 10, 10); // 赋值一个 Vector3 向量
this.transform.localPosition = Vector3.up * 10; // 只要是 Vector3 就可以

如果只想改坐标中 x 值,y 和 z 保持原有坐标一致,有两种方法:

  • 直接赋值,y 和 z 的值放到新的 Vector3 上:
this.transform.position = new Vector3(19, this.transform.position.y, this.transform.position.z);
  • 先取出 Vector3,再赋值:
// 虽然不能直接改 transform 的 xyz,但是 Vector3 是可以直接改 xyz 的,所以可以先取出来改 Vector3,再重新赋值
Vector3 vPos = this.transform.localPosition;
vPos.x = 10;
this.transform.localPosition = vPos;

Transform.朝向 得到对象当前的一个朝向

// 对象当前的各朝向
print(this.transform.forward); // 对象当前的面朝向
print(this.transform.up); // 对象当前的头顶朝向
print(this.transform.right); // 对象当前的右手边

位移

理解坐标系下的位移计算公式

  • 路程 = 方向 * 速度 * 时间
  • 因为位移每一帧都要动,所以放在 Update 里
手动计算position
// 想要变化的就是 position,修改 position 即可。
// 用当前的位置 + 移动的方向向量 * 每帧移动的距离(可以理解为速度) * 每帧时间,得出最终每帧所在的位置。
// this.transform.position = this.transform.position + this.transform.up * 1 * Time.deltaTime;
//可以使用 += -=
// 因为用的是 this.transform.forward,所以它始终会朝向相对于自己的面朝向去动。
// this.transform.position += this.transform.forward * 1 * Time.deltaTime;
// 因为用的是 Vector3.forward,所以它始终会朝向相对于世界坐标系的面朝向去动。
// this.transform.position += Vector3.forward * 1 * Time.deltaTime;
// 方向非常重要,因为它决定了你的前进方向。
Transform.Translate方法 位移
// 根据 translation 的方向和距离移动变换。

// 参数一:每帧位移多少,每帧位移 = 移动的方向向量 * 每帧移动的距离(可以理解为速度) * 每帧时间。
// 参数二:相对坐标系,默认不填的话,该参数是相对于自己坐标系的。

// 移动的方向向量:Vector3.forward,相对坐标系:Space.World
// 相对于世界坐标系的 Z 轴动,始终是朝世界坐标系的 Z 轴正方向移动。
// this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.World);

// 移动的方向向量:this.transform.forward,相对坐标系:Space.World
// 相对于世界坐标的自己的面朝向去动,始终朝自己的面朝向移动。
// this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.World);

// 移动的方向向量:Vector3.forward,相对坐标系:Space.Self
// 相对于自己的坐标系下的 Z 轴正方向移动,始终朝自己的面朝向移动。
// this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.Self);

// 移动的方向向量:this.transform.forward,相对坐标系:Space.Self
// 相对于自己的坐标系下的自己的面朝向向量移动(一般不会这样让物体移动,双重叠加了偏移)。
// this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.Self);

注意:一般使用 Translate 方法来进行位移。

总结

  • Vector3:如何申明,提供的常用静态属性和一个计算距离的方法。
  • 位置:相对于世界坐标系和相对于父对象这两个坐标的区别,不能够单独修改 xyz,只能一起统一改。
  • 位移:自己如何计算来进行位移,API 是哪个方法来进行位移,使用时要注意。

16.2 知识点代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson16_必不可少Transform_位置和位移 : MonoBehaviour
{    
    void Start()
    {
        #region Transform主要用来干嘛?
        //游戏对象(GameObject)位移、旋转、缩放、父子关系、坐标转换等相关操作都由它处理
        //它是Unity提供的极其重要的类
        #endregion

        #region 知识点一 Vector3基础

        //Vector3主要是用来表示三维坐标系中的 一个点 或者一个向量
        //用于表示 3D 向量和点。
        //Unity 内部使用该结构传递 3D 位置和方向。 此外,它还包含用于执行常见向量操作的函数。
        //除了下面列出的函数以外,也可以使用其他类操作向量和点。 例如,对于旋转或变换向量和点来说,Quaternion 和 Matrix4x4 类也很有用。

        //Vector3的申明

        //无参构造 后赋值
        Vector3 v1 = new Vector3();
        v1.x = 10;
        v1.y = 10;
        v1.z = 10;

        //传xy坐标参数的构造 默认z是0
        Vector3 v2 = new Vector3(10, 10);

        //传xyz坐标参数的参数构造 一步到位
        Vector3 v3 = new Vector3(10, 10, 10);

        //结构体直接声明Vector3变量 后赋值
        Vector3 v4;
        v4.x = 10;
        v4.y = 10;
        v4.z = 10;

        //Vector的基本计算
        // + - * / 加减乘除
        Vector3 v11 = new Vector3(1, 1, 1);
        Vector3 v12 = new Vector3(2, 2, 2);
        print(v11 + v12);//(3.0, 3.0, 3.0)
        print(v11 - v12);//(-1.0, -1.0, -1.0)
        print(v11 * 10);//(10.0, 10.0, 10.0)
        print(v12 / 2);//(1.0, 1.0, 1.0)

        //Vector3常用的向量供我们使用
        print(Vector3.zero);//000
        print(Vector3.right);//100
        print(Vector3.left);//-100
        print(Vector3.up);//010
        print(Vector3.down);//0-10
        print(Vector3.forward);//001
        print(Vector3.back);//00-1

        //Distance方法 计算两个点之间的距离的方法
        //返回 a 与 b 之间的距离。
        print(Vector3.Distance(v11, v12));//1.732051

        #endregion

        #region 知识点二 位置

        //position变量 相对世界坐标系的坐标
        //世界空间中的变换位置。
        print(this.transform.position);
        //通过position得到的位置 是相对于 世界坐标系的 原点的位置
        //可能和面板上显示的 是不一样的
        //因为如果对象有父子关系 并且父对象位置 不在原点 那么 和面板上肯定就是不一样的

        //localPosition变量 相对父对象的坐标
        //相对于父变换的变换位置。
        print(this.transform.localPosition);
        //这两个坐标 对于我们来说 很重要 如果你想以面板坐标为准来进行位置设置
        //那一定是通过localPosition来进行设置的

        //position和localPosition值相等的情况
        //1.父对象的坐标 就是世界坐标系原点0,0,0
        //2.对象没有父对象 

        //注意:位置的赋值不能直接改变x,y,z 只能整体改变
        //不能单独改 x y z某一个值
        //this.transform.position.x = 10;//报错
        this.transform.position = new Vector3(10, 10, 10);//赋值一个Vector3向量
        this.transform.localPosition = Vector3.up * 10;//只要是Vector3就可以

        //如果只想改坐标中x值 y和z保持原有坐标一致 有两种方法
        //1.直接赋值 y和z的值放到新的Vector3上
        this.transform.position = new Vector3(19, this.transform.position.y, this.transform.position.z);
        //2.先取出Vector3 再赋值
        //虽然不能直接改 transform的 xyz 但是 Vector3是可以直接改 xyz的
        //所以可以先取出来改Vector3 再重新赋值
        Vector3 vPos = this.transform.localPosition;
        vPos.x = 10;
        this.transform.localPosition = vPos;

        //transform.朝向 得到对象当前的 一个朝向 
        //对象当前的各朝向
        print(this.transform.forward);//对象当前的面朝向
        print(this.transform.up);//对象当前的头顶朝向
        print(this.transform.right);//对象当前的右手边

        #endregion
    }
    
    void Update()
    {
        #region 知识点三 位移

        //理解坐标系下的位移计算公式
        //路程 = 方向 * 速度 * 时间
        //因为位移每一帧都要动 所以放在Update里

        //手动计算position
        //想要变化的 就是 position 修改position即可
        //用当前的位置 + 移动的方向向量*每帧移动的距离(可以理解为速度)*每帧时间  得出最终每帧所在的位置 
        //this.transform.position = this.transform.position + this.transform.up * 1 * Time.deltaTime;
        //可以使用+= -=
        //因为用的是 this.transform.forward 所以它始终会朝向相对于自己的面朝向去动
        //this.transform.position += this.transform.forward * 1 * Time.deltaTime;
        //因为用的是 Vector3.forward 所以它始终会朝向相对于世界坐标系的面朝向去动
        //this.transform.position += Vector3.forward * 1 * Time.deltaTime;
        //方向非常重要 因为 它决定了你的前进方向

        //Translate方法
        //根据 translation 的方向和距离移动变换。
        //参数一:每帧位移多少 每帧位移=移动的方向向量*每帧移动的距离(可以理解为速度)*每帧时间
        //参数二:相对坐标系 默认不填的话 该参数 是相对于自己坐标系的

        //移动的方向向量:Vector3.forward 相对坐标系:Space.World
        //相对于世界坐标系的 Z轴 动  始终是朝 世界坐标系 的 Z轴正方向移动
        //this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.World);

        //移动的方向向量:this.transform.forward 相对坐标系:Space.World
        //相对于世界坐标的 自己的面朝向去动 始终朝自己的面朝向移动
        //this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.World);

        //移动的方向向量:Vector3.forward 相对坐标系:Space.Self
        //相对于自己的坐标系 下的 Z轴正方向移动  始终朝自己的面朝向移动
        //this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.Self);

        //移动的方向向量:this.transform.forward 相对坐标系:Space.Self
        //相对于自己的坐标系 下的 自己的面朝向向量移动 (一般不会这样让物体移动,双重叠加了偏移)
        //this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.Self);

        //注意:一般使用Translate方法来进行位移

        #endregion
    }

    //总结
    //Vector3:如何申明 提供的 常用静态属性 和一个 计算距离的方法 
    //位置:相对于世界坐标系 和 相对于父对象 这两个坐标的区别 不能够 单独修改 xyz  只能一起统一改 
    //位移:自己如何计算来进行位移 API是哪个方法 来进行位移 使用时 要注意
}

16.3 练习题

一个空对象上挂了一个脚本,这个脚本可以让游戏运行时,在场景中创建出一个n层由Cube构成的金字塔(提示:实例化预设体或者实例化自带几何体方法)


//决定层数
for (int i = 0; i < n; i++)
{
    //每一层开始创建时 应该得到一个 初始的坐标
    Vector3 pos = new Vector3(-0.5f * i, -1 * i, 0.5f * i);

    //决定每层多少个立方体
    for (int j = 0; j < (i + 1) * (i + 1); j++)
    {
        //实例化 立方体 
        GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
        //然后设置位置
        //因为 是起始位置 + 偏移位置 所以 Y不用变
        obj.transform.position = pos + new Vector3(j % (i + 1) * 1, 0, j / (i + 1) * -1);
    }
}

这四个方法,哪些才能让对象朝自己的面朝向移动?为何?(可以画图说明)

this.transform.Translate(Vector3.forward, Space.World);
this.transform.Translate(Vector3.forward, Space.Self);
this.transform.Translate(this.transform.forward, Space.Self);
this.transform.Translate(this.transform.forward, Space.World);

//this.transform.Translate(Vector3.forward, Space.World); //始终是朝向世界坐标系的Z轴移动的
//this.transform.Translate(Vector3.forward, Space.Self);  //始终是朝向自己的面朝向移动的
//this.transform.Translate(this.transform.forward, Space.Self); //你也不知道朝哪里动 XXXXX
//this.transform.Translate(this.transform.forward, Space.World);//始终是朝向自己的面朝向移动的
  • 可以理解为 this.transform和Space.Self都会根据当前对象坐标系和世界坐标系的偏移差计算后,进行偏移,this.transform.Translate(this.transform.forward, Space.Self);叠加了两次偏移所以不知道朝哪里动

使用你之前创建的坦克预设体,让其可以朝自己的面朝向向前移动

预制体要注意面朝z轴正方向

//在Update内
//this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.Self);
this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.World);

16.4 练习题代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson16_练习题 : MonoBehaviour
{
    public int n = 10;
    
    void Start()
    {
        #region 练习题一
        //1.一个空对象上挂了一个脚本,这个脚本可以让游戏运行时,
        //在场景中创建出一个n层由Cube构成的金字塔(提示:实例化预设体或者实例化自带几何体方法)

        //决定层数
        for (int i = 0; i < n; i++)
        {
            //每一层开始创建时 应该得到一个 初始的坐标
            Vector3 pos = new Vector3(-0.5f * i, -1 * i, 0.5f * i);

            //决定每层多少个立方体
            for (int j = 0; j < (i + 1) * (i + 1); j++)
            {
                //实例化 立方体 
                GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
                //然后设置位置
                //因为 是起始位置 + 偏移位置 所以 Y不用变
                obj.transform.position = pos + new Vector3(j % (i + 1) * 1, 0, j / (i + 1) * -1);
            }

        }

        #endregion

        #region 练习题二
        //2.
        //this.transform.Translate(Vector3.forward, Space.World);
        //this.transform.Translate(Vector3.forward, Space.Self);
        //this.transform.Translate(this.transform.forward, Space.Self);
        //this.transform.Translate(this.transform.forward, Space.World);
        //这四个方法,哪些才能让对象朝自己的面朝向移动?为何?(可以画图说明)


        //this.transform.Translate(Vector3.forward, Space.World); //始终是朝向 世界坐标系的 Z轴移动的
        //this.transform.Translate(Vector3.forward, Space.Self);  //始终是朝向自己的面朝向移动的
        //this.transform.Translate(this.transform.forward, Space.Self); //你也不知道朝哪里动 XXXXX
        //this.transform.Translate(this.transform.forward, Space.World);//始终是朝向自己的面朝向移动的

        #endregion
    }

    void Update()
    {
        #region 练习题三
        //3.使用你之前创建的坦克预设体,让其可以朝自己的面朝向向前移动

        //在Update内
        //this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.Self);
        this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.World);

        #endregion
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏