一、什么是Transform?

 场景中的每一个物体都有一个Transform,用于存储和操作对象的位置、旋转和缩放,存在层级关系(父级和子级)。

二、常用变量与属性(位置)

1.位置

position:世界坐标

localposition:相对坐标(父物体就是世界,相对于父物体的坐标)

private void OnGUI()
    {
        //世界坐标
        GUILayout.Label(string.Format("Transform's position:{0}", transform.position));
        //相对坐标
        GUILayout.Label(string.Format("Transform's localPosition:{0}", transform.localPosition));
    }

2.角度

enlerAnles,localEnlerAnles欧拉角;rotation,localRotation四元数旋转角度(自然数)。

private void OnGUI()
    {
        //相对世界的欧拉角
        GUILayout.Label(string.Format("Transform's eulerAngles:{0}", transform.eulerAngles));
        //相对父物体的欧拉角
        GUILayout.Label(string.Format("Transform's localEulerAngles:{0}", transform.localEulerAngles));
        //相对世界的rotation
        GUILayout.Label(string.Format("Transform's rotation:{0}", 
transform.rotation));
        //相对父物体的rotation
        GUILayout.Label(string.Format("Transform's localRotation:{0}", transform.localRotation));
        //欧拉角转换成自然数方式
        transform.rotation = Quaternion.EulerAngles(270, 0, 0);
    }

3.缩放

localScale相对父级缩放比例;lossyScale相对世界缩放比例。

private void OnGUI()
    {
        //相对父级缩放
        GUILayout.Label(string.Format("Transform's localScale:{0}", transform.localScale));
        //相对世界的缩放
        GUILayout.Label(string.Format("Transform's lossyScale:{0}", transform.lossyScale));
    }

4.其他

right(向左),up(向上),forward(向前)方向向量。

private void OnGUI()
    {
        //向右
        GUILayout.Label(string.Format("Transform's right:{0}", transform.right));
        //向上
        GUILayout.Label(string.Format("Transform's up:{0}", transform.up));
        //向前
        GUILayout.Label(string.Format("Transform's forward:{0}", transform.forward));
    }

parent(父级),root(根物体),childCount(多少个子级)子父级相对。

unity脚本添加子物体 unity添加脚本没有transform_缓存

private void OnGUI()
    {
        //向右
        GUILayout.Label(string.Format("Transform's right:{0}", transform.parent.name));
        //向上
        GUILayout.Label(string.Format("Transform's up:{0}", transform.root.name));
        //向前
        GUILayout.Label(string.Format("Transform's forward:{0}", transform.childCount));
    }

三、移动

1.直接修改位置

小技巧:优化,缓存和不缓存。

public Transform trans;
    public int Count = 1000;     //缓存次数
    private long NoCache = 0;    //不缓存
    private long Cache = 0;    //缓存
    // Start is called before the first frame update
    void Start()
    {
        trans = this.transform; //获得trans,能提高效率,缓存

        Stopwatch sw = new Stopwatch();
        sw.Start();       //启动Stopwatch
        for (int i = 0; i < Count; i++) {     //循环次数
            Transform t = this.transform;
        }
        sw.Stop();
        NoCache = sw.ElapsedTicks;

        sw.Reset();

        sw.Start();
        for (int i = 0; i < Count; i++) {
            Transform t = trans;      //直接获取trans
        }
        sw.Stop();
        Cache = sw.ElapsedTicks;
    }

    private void OnGUI()
    {
        //向右
        GUILayout.Label(string.Format("Transform's NoCache:{0}", NoCache));
        //向上
        GUILayout.Label(string.Format("Transform's Cache:{0}", Cache));
    }

unity脚本添加子物体 unity添加脚本没有transform_Time_02

移动

public Transform trans;
    private bool moveToLeft = true;  //控制左右移动
    private float speed = 2;

    // Start is called before the first frame update
    void Start()
    {
        trans = this.transform; //获得trans,能提高效率,缓存

    }
      
    // Update is called once per frame
    void Update()
    {
      Move();
      //  trans.position = new Vector3(Random.Range(-3f, 3f), Random.Range(-3f, 3f), Random.Range(-3f, 3f)); //直接移动,随机移动,随机数-3*3
      //  trans.position = new Vector3(Random.Range(-3f, 3f), Random.Range(-3f, 3f), Random.Range(-3f, 3f)); //直接移动,随机移动,随机数-3*3
    }

    private void Move()
    {
        if (trans.position.x <= -3 && moveToLeft) {     //在x轴-3到3移动,向左移动为true
            moveToLeft = false;    //向右移动
        } else if(trans.position.x >= 3 && !moveToLeft){
            moveToLeft = true;      //向左移动
        }
       trans.position += (moveToLeft?Vector3.left : Vector3.right) * Time.deltaTime * speed;  //判断向左向右,后面的话是指每秒;如果向左移动,每秒钟向左移动两个单位。。。
    }

2.Translate函数

1.1 依据自身坐标移动

private void Translate()
    {
        if (transform.position.x < -3 && moveToLeft)
        {     //在x轴-3到3移动,向左移动为true
            moveToLeft = false;    //向右移动
        }
        else if (transform.position.x >= 3 && !moveToLeft)
        {
            moveToLeft = true;      //向左移
        }
        transform.Translate((moveToLeft ? Vector3.left : Vector3.right) * Time.deltaTime * speed, Space.Self);
    }

1.2 space可以控制是沿自身方向(space.Self)移动还是沿世界方向(space.World)移动。

下面这段代码是沿着世界向前移动。

public Transform trans;
 void Start()
    {
        trans = this.transform;
    }
 void Update()
    {
        Translate(Space.World);
}
 private void Translate(Space space) {
        trans.Translate(Vector3.forward *Time.deltaTime *2, space);
    }

四、旋转

1.直接修改欧拉角和旋转角

修改eulerAngles欧拉角和rotation定义旋转角度代码如下:

public Transform trans;
    public float speed = 90;

    private void Start() {
        trans = this.transform;
            }
    private void Update()
    {
        //  trans.eulerAngles = new Vector3(0, 0, 45);      //在z轴旋转45°
        trans.eulerAngles = new Vector3(0, 0, 45);      //相对父级
        trans.rotation = Quaternion.Euler(0,0,45);       // 
        trans.localRotation = Quaternion.Euler(0, 0, 45);     //相对父级

                // trans.eulerAngles += Time.deltaTime * speed * Vector3.forward;    //沿着z轴旋转
        trans.rotation = Quaternion.Euler(trans.eulerAngles.x, trans.eulerAngles.y, trans.eulerAngles.z + Time.deltaTime *speed); //沿着z轴旋转
    }

2. Rotate,RotateAround和LookAt函数

2.1 Rotate函数实现旋转功能跟修改欧拉角和旋转角进行旋转有一样的效果,只需要填写一个方向和旋转的速度。

private void Rotate() {
        trans.Rotate(Vector3.forward * Time.deltaTime * speed);     //跟修改欧拉角和旋转角进行旋转有一样的效果,只需要填写一个方向和旋转的速度
    }

2.2 RotateAround函数实现sphere围绕cube旋转,代码如下:

public Transform target;    //围绕的点

    private void Rotate() {
        trans.RotateAround(target.position, target.up, Time.deltaTime *speed); //围绕旋转的点、轴向、速度
    }

unity脚本添加子物体 unity添加脚本没有transform_缩放_03

2.3 LookAt函数,z轴看向,比如把sphere移动一下,cube也是一直始终看向sphere。

public Transform target;    //围绕的点
    private void LookAt() {
        trans.LookAt(target);
    }

3.利用right,up,forward改变方向

private void ChangeDir() {
        Vector3 dir = target.position - trans.position;    //trans指向target
        trans.up = dir;      
    }

五、缩放

1.直接修改缩放比例

public Transform trans;
    public float speed = 1;
    public bool ZoomInt;    //放大还是缩小

    private void Start()
    {
        trans = this.transform;
    }
    private void Update()
    {
        Zoom();
    }

    public void Zoom() {
        if (trans.localScale.x <= 0 && !ZoomInt) {     //放大
            ZoomInt = true;
        } else if(trans.localScale.x <=3 && ZoomInt)       //缩小
        {
            ZoomInt = false;
        }
        trans.localScale += (ZoomInt ? Vector3.right : Vector3.left) * Time.deltaTime*speed;      //是否放大,left相当于-right
    }

五、其他常用函数

1. TransformDirection和InverseTransformDirection

1.1 TransformDirection可以实现人物可以朝着摄像机的方向移动而不一定是世界坐标,把希望的方向转给trans,代码如下。

public Transform trans;

    private void Start()
    {
        trans = this.transform;
    }
    private void Update()
    {
        Debug.DrawRay(trans.position, trans.TransformDirection(Camera.main.transform.forward) *10, Color.red);     // Debug.DrawRay()画一根线,从trans的位置
    }

1.2 InverseTransformDirection,处理镜像运动。

Debug.DrawRay(trans.position, trans.InverseTransformDirection(Camera.main.transform.forward) * 10, Color.yellow);

2. DetachChilder,Find,GetChild和IsChildOf

private Transform trans;

    public Transform Child;

    private void Start()
    {
        trans = this.transform;
    }
    private void Update()
    {
    }
    private string _IsChild;   //记录
    private void OnGUI()
    {
        if (GUILayout.Button("Detch Children")) {         //将当前transform下的子物体分离出来,取消他们的一个关系
            trans.DetachChildren();
        }
        if (GUILayout.Button("Find Children"))           //查找"Child"
        {
            trans.Find("Child").position = Vector3.one * 3;
        }
        if (GUILayout.Button("GetChildren"))         //获得子物体的方式,是根据索引值来获取的
        {
            trans.GetChild(0).position = Vector3.one * 5;
        }
        if (GUILayout.Button("IsChildOf"))            //检测当前transform是不是我们参数里填的transform的子物体
        {
            _IsChild = Child.IsChildOf(trans).ToString();
        }
        GUILayout.Label(_IsChild);
    }

unity脚本添加子物体 unity添加脚本没有transform_Time_04