19.Transform变换组件父子关系

19.Unity重要组件和API-Transform父子关系


19.1 知识点

获取和设置父对象

parent变量 获取父对象 返回父对象的transform

// 变换的父级。
// print(this.transform.parent);
// print(this.transform.parent.name);

this.transform.parent = 设置父对象

// 断绝父子关系
// this.transform.parent = null;
// 认爸爸
// this.transform.parent = GameObject.Find("Father2").transform;

SetParent方法 设置父对象

// 设置变换的父级。
// 参数一:父对象
// 参数二:是否保留世界坐标的位置、角度、缩放信息
// 如果为 true,则修改相对于父级的位置、缩放和旋转,使对象保持与之前相同的世界空间位置、旋转和缩放。
// true 会保留世界坐标下的状态和父对象进行计算,得到本地坐标系的信息
// false 不会保留,会直接把世界坐标系下的位置、角度、缩放直接赋值到本地坐标系下,可以理解为粗暴的把世界坐标下的变换赋值到面板上
// this.transform.SetParent(null); // 断绝父子关系
// this.transform.SetParent(GameObject.Find("Father2").transform); // 认爸爸
// this.transform.SetParent(GameObject.Find("Father3").transform, false);

断绝与所有子对象的关系

DetachChildren方法 断绝与所有子对象的关系

// 清除所有子项的父级。
// 注意:不能影响自己的儿子和孙子的关系,只能断绝自己和儿子的关系
// this.transform.DetachChildren();

获取子对象

Find方法 按名字查找儿子 找到儿子的 transform信息

// 按名字查找子项,然后返回它。
// print(this.transform.Find("Cube (1)").name);
// Find 方法能够找到失活的对象!!!!! GameObject 相关的查找不能找到失活对象,它只能找到自己的儿子,找不到自己的孙子!!!!!!
// 虽然它的效率比 GameObject.Find 相关要高一些,但是前提是你必须知道父亲是谁才能找到

childCount变量 得到有多少个儿子

// 父变换具有的子项数。
// 失活的儿子也会算在内,只会找儿子不找孙子,所以孙子不会算数量
// print(this.transform.childCount);

GetChild方法 遍历所有儿子

for (int i = 0; i < this.transform.childCount; i++)
{
    print("儿子的名字:" + this.transform.GetChild(i).name);
}

儿子的操作

IsChildOf方法 判断自己的爸爸是谁

// 该变换是否为 parent 的子项?
// 一个对象判断自己是不是另一个对象的儿子
// if (son.IsChildOf(this.transform))
// {
//    print("是我的儿子");
// }

GetSiblingIndex方法 得到自己作为儿子的编号

// 获取同级索引。
// print(son.GetSiblingIndex());

SetAsFirstSibling方法 把自己设置为第一个儿子

// 将变换移动到本地变换列表的开头。
// son.SetAsFirstSibling();

SetAsLastSibling方法 把自己设置为最后一个儿子

// 将变换移动到本地变换列表的末尾。
// son.SetAsLastSibling();

SetSiblingIndex方法 把自己设置为指定个儿子

// 设置同级索引。
// 就算你填的数量超出了范围(负数或者更大的数)也不会报错,会直接设置成最后一个编号
// son.SetSiblingIndex(1);

总结

  • 获取和设置父对象相关的内容
  • 获取子对象
  • 抛弃妻子
  • 儿子的操作

19.2 知识点代码

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

public class Lesson19_必不可少Transform_父子关系 : MonoBehaviour
{
    public Transform son;
    
    void Start()
    {
        #region 知识点一 获取和设置父对象

        //parent变量 获取父对象 返回父对象的transform
        //变换的父级。
        //print(this.transform.parent);
        //print(this.transform.parent.name);

        //this.transform.parent = 设置父对象
        //断绝父子关系
        //this.transform.parent = null;
        //认爸爸
        //this.transform.parent = GameObject.Find("Father2").transform;

        //SetParent方法 设置父对象
        //设置变换的父级。
        //参数一:父对象
        //参数二:是否保留世界坐标的 位置 角度 缩放 信息
        //如果为 true,则修改相对于父级的位置、缩放和旋转,使对象保持与之前相同的世界空间位置、旋转和缩放。
        //true  会保留 世界坐标下的状态  和 父对象 进行计算 得到本地坐标系的信息
        //false 不会保留 会直接把世界坐标系下的 位置角度缩放 直接赋值到 本地坐标系下 可以理解为粗暴的把世界坐标下的变换赋值到面板上
        //this.transform.SetParent(null);//断绝父子关系
        //this.transform.SetParent(GameObject.Find("Father2").transform);//认爸爸
        //this.transform.SetParent(GameObject.Find("Father3").transform, false);

        #endregion

        #region 知识点二 抛妻弃子

        //DetachChildren方法 就是和自己的所有儿子 断绝关系 没有父子关系了
        //清除所有子项的父级。
        //注意:不能影响自己儿子和孙子的关系 只能断绝自己和儿子的关系
        //this.transform.DetachChildren();

        #endregion

        #region 知识点三 获取子对象

        //Find发明方法 按名字查找儿子 找到儿子的 transform信息
        //按 n 查找子项,然后返回它。
        print(this.transform.Find("Cube (1)").name);
        //Find方法 是能够找到 失活的对象的 !!!!! GameObject相关的 查找 是不能找到失活对象的
        //他只能找到自己的儿子 找不到自己的孙子 !!!!!!
        //print(this.transform.Find("Cube (1)(2)").name);
        //虽然它的效率 比GameObject.Find相关 要高一些 但是 前提是你必须知道父亲是谁 才能找
      
        //childCount方法 得到有多少个儿子
        //父变换具有的子项数。
        //失活的儿子也会算数量
        //只会找儿子不找孙子 所以孙子不会算数量
        print(this.transform.childCount);

        //GetChild方法 通过索引号 去得到自己对应的儿子
        //按索引返回变换子项。
        //如果编号 超出了儿子数量的范围 那会直接报错的 
        //返回值 是 transform 可以得到对应儿子的 位置相关信息
        this.transform.GetChild(0);

        //遍历所有儿子
        for (int i = 0; i < this.transform.childCount; i++)
        {
            print("儿子的名字:" + this.transform.GetChild(i).name);
        }

        #endregion

        #region 知识点四 儿子的操作

        //IsChildOf方法 判断自己的爸爸是谁
        //该变换是否为 parent 的子项?
        //一个对象 判断自己是不是另一个对象的儿子
        //if (son.IsChildOf(this.transform))
        //{
        //    print("是我的儿子");
        //}

        //GetSiblingIndex方法得到自己作为儿子的编号
        //获取同级索引。
        //print(son.GetSiblingIndex());

        //SetAsFirstSibling方法 把自己设置为第一个儿子
        //将变换移动到本地变换列表的开头。
        //son.SetAsFirstSibling();

        //SetAsLastSibling方法 把自己设置为最后一个儿子
        //将变换移动到本地变换列表的末尾。
        //son.SetAsLastSibling();

        //SetSiblingIndex方法 把自己设置为指定个儿子
        //设置同级索引。
        //就算你填的数量 超出了范围(负数或者更大的数) 也不会报错 会直接设置成最后一个编号
        //son.SetSiblingIndex(1);

        #endregion
    }

    //总结
    //设置父对象相关的内容
    //获取子对象
    //抛弃妻子
    //儿子的操作
}

19.3 练习题

请为Transform写一个拓展方法,可以将它的子对象按名字的长短进行排序改变他们的顺序,名字短的在前面,名字长的在后面

设置一个拓展方法类:

public static class Lesson19_练习题拓展方法
{
}

为Transform添加名字排序的拓展方法:

/// <summary>
/// 这个方法 是我们为Transform写的一个拓展方法
/// 主要用来把子对象按名字长短排序
/// </summary>
/// <param name="obj"></param>
public static void Sort(this Transform obj)
{
    //有什么知识点 是和排序相关
    //使用List的排序 比较符合我们的需求
    //我们的思路 就是把子对象 放到一个 list容器中 然后对list进行排序 
    //排序完毕后 遍历list 去设置 这个顺序中的 对象的 子对象位置

    //遍历添加子对象到子对象list中
    List<Transform> list = new List<Transform>();
    for (int i = 0; i < obj.childCount; i++)
    {
        list.Add(obj.GetChild(i));
    }

    //这是根据 名字长短进行排序 利用的 是list的排序 传个函数进去
    list.Sort(
                (a, b) =>
                {
                    if (a.name.Length < b.name.Length)
                        return -1;
                    else
                        return 1;
                }
            );

    //根据 list中的排序结果 重新设置每一个对象的 索引编号
    for (int i = 0; i < list.Count; i++)
    {
        list[i].SetSiblingIndex(i);
    }

}

调用添加名字排序的拓展方法:

this.transform.Sort();

请为Transform写一个拓展方法,传入一个名字查找子对象,即使是子对象的子对象也能查找到

为Transform添加搜索全部子对象的拓展方法:

/// <summary>
/// 根据名字找到 子对象 不管藏多深
/// </summary>
/// <param name="father">调用方法的对象</param>
/// <param name="childName">要找的对象名字</param>
/// <returns></returns>
public static Transform CustomFind(this Transform father, string childName)
{
    //如何查找子对象的子对象

    //我要找的对象
    Transform target = null;

    //先从自己身上的子对象找
    target = father.Find(childName);
    if (target != null)
        return target;

    //如果在自己身上没有找到 那就遍历的去找自己的子对象的子对象
    for (int i = 0; i < father.childCount; i++)
    {
        //让子对象去帮我找 有没有这个名字的对象
        //递归查找
        target = father.GetChild(i).CustomFind(childName);
        //找到了 直接返回
        if (target != null)
            return target;
    }

    return target;
}

调用搜索全部子对象的拓展方法:

print(this.transform.CustomFind("林文韬").name);

19.4 练习题代码

Lesson19_练习题

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

public class Lesson19_练习题 : MonoBehaviour
{
    void Start()
    {
        #region 练习题一
        //请为Transform写一个拓展方法,可以将它的子对象按名字的长短进行排序改变他们的顺序,
        //名字短的在前面,名字长的在后面
        this.transform.Sort();
        #endregion

        #region 练习题二
        //请为Transform写一个拓展方法,传入一个名字查找子对象,即使是子对象的子对象也能查找到
        print(this.transform.CustomFind("林文韬").name);
        #endregion
    }
}

Lesson19_练习题拓展方法

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

public static class Lesson19_练习题拓展方法
{
    /// <summary>
    /// 这个方法 是我们为Transform写的一个拓展方法
    /// 主要用来把子对象按名字长短排序
    /// </summary>
    /// <param name="obj"></param>
    public static void Sort(this Transform obj)
    {
        //有什么知识点 是和排序相关
        //使用List的排序 比较符合我们的需求
        //我们的思路 就是把子对象 放到一个 list容器中 然后对list进行排序 
        //排序完毕后 遍历list 去设置 这个顺序中的 对象的 子对象位置

        //遍历添加子对象到子对象list中
        List<Transform> list = new List<Transform>();
        for (int i = 0; i < obj.childCount; i++)
        {
            list.Add(obj.GetChild(i));
        }

        //这是根据 名字长短进行排序 利用的 是list的排序 传个函数进去
        list.Sort(
                    (a, b) =>
                    {
                        if (a.name.Length < b.name.Length)
                            return -1;
                        else
                            return 1;
                    }
                );

        //根据 list中的排序结果 重新设置每一个对象的 索引编号
        for (int i = 0; i < list.Count; i++)
        {
            list[i].SetSiblingIndex(i);
        }
    }


    /// <summary>
    /// 根据名字找到 子对象 不管藏多深
    /// </summary>
    /// <param name="father">调用方法的对象</param>
    /// <param name="childName">要找的对象名字</param>
    /// <returns></returns>
    public static Transform CustomFind(this Transform father, string childName)
    {
        //如何查找子对象的子对象

        //我要找的对象
        Transform target = null;

        //先从自己身上的子对象找
        target = father.Find(childName);
        if (target != null)
            return target;

        //如果在自己身上没有找到 那就遍历的去找自己的子对象的子对象
        for (int i = 0; i < father.childCount; i++)
        {
            //让子对象去帮我找 有没有这个名字的对象
            //递归查找
            target = father.GetChild(i).CustomFind(childName);
            //找到了 直接返回
            if (target != null)
                return target;
        }

        return target;
    }
}


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

×

喜欢就点赞,疼爱就打赏