深度优先及广度优先在Unity中的应用

Posted gangtie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度优先及广度优先在Unity中的应用相关的知识,希望对你有一定的参考价值。

说明:

简单总结一下深度优先算法和广度优先算法在Unity中最直观和最多见的使用。这里我所举的例子是应用到Unity中3D 人物的全部骨骼关键的遍历,推广开就是能够对全部物体的层级关系进行简单的遍历。。。算法

数据结构中的树的遍历在Unity中最直观的表现就是对某物体的全部子物体的遍历关系。数据结构

以下所示就是对Unity全部子物体层级的转换出的数据结构(树)3d

技术图片技术图片

 

深度优先遍历:

深度优先遍历是按照树(图)的深度遍历的一种遍历算法。主要是基于深度优先,既是从某一节点V做为起始节点开始进行遍历,当V的的某一边里全部都遍历事后,回溯到起始节点V,而后继续对另外一条边进行遍历,直至全部节点被遍历完成为止。
如上图所示的树,深度优先的遍历方式为:
  1. A做为Root结点,第一个被访问,而后依次访问B、E、K,当这条路走完后,接着访问L,而后访问F,这样就表明第一条边被访问完成;
  2. 而后回溯到A,依次访问C、G
  3. 最后在回溯到A,依次访问D、H、M、I、J
在Unity中深度遍历全部子物体以下所示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 深度优先
/// </summary>
public class DepthFirst : MonoBehaviour
{
    //用于存储所遍历到的物体
    List<Transform> DepthFirstList = new List<Transform>();
    
    void Start()
    {
        DepthFirst_0(transform);
        //打印序列
        foreach (var item in DepthFirstList)
        {
            Debug.Log(item);
        }
    }

    void DepthFirst_0(Transform tran)
    {
        foreach (Transform item in tran)
        {
            DepthFirstList.Add(item);
            //判断是否存在子物体
            if (item.childCount != 0)
            {
                DepthFirst_0(item);
            }
        }
    }
}
打印结果以下所示:
技术图片
 

广度优先遍历

广度优先遍历是按照树(图)的广度遍历的一种遍历算法(又称为层次遍历)。主要是基于广度优先,既是某一节点V做为起始节点开始进行遍历,沿着树(图)的层次进行依次遍历,当第N层被遍历完成后,进行第N+1层遍历,当全部节点都比访问后,遍历完成。
如上图所示的树,广度优先的遍历方式为:
  1. A做为Root结点,做为第一层被访问,当第一层访问完成,切到第二层
  2. 而后依次访问第二层:B、C、D,第二层访问完成
  3. 而后依次访问第三层:E、F、G、H、I、J,第三层访问完成
  4. 而后依次访问第四层:K、L、M
  5. 没有第4+1层,遍历完成
在Unity中广度遍历全部子物体以下所示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 获取全部关键
/// </summary>
public class BreathFirst : MonoBehaviour
{
    List<Transform> BreadthFirstList = new List<Transform>();//层次遍历所获得的List

    /// <summary>
    /// 首先把物体的第一层子物体放入一个List,便于以后使用
    /// </summary>
    void Start()
    {
        List<Transform> joinsList = new List<Transform>();
        foreach (Transform itemJoins in transform)
        {
            joinsList.Add(itemJoins);
        }
        BreadthFirst_1(joinsList);

        foreach (var item in BreadthFirstList)
        {
            Debug.Log(item);
        }
    }

    /// <summary>
    /// 递归遍历每一层
    /// </summary>
    /// <param name="joins"></param>
    void BreadthFirst_1(List<Transform> joins)
    {
        List<Transform> joinsChildListss = new List<Transform>();
        foreach (Transform item in joins)
        {
            BreadthFirstList.Add(item);//将每一层依次放入列表中
            if (item.childCount != 0)//判断每一次的序列项是否存在子物体,存在就将全部子物体放入一个新的List
            {
                foreach (Transform itemss in item)
                {
                    joinsChildListss.Add(itemss);
                }
            }
        }
        if (joinsChildListss != null && joinsChildListss.Count != 0)//判断是不是最后一层
            BreadthFirst_1(joinsChildListss);
    }
}

打印结果以下所示:
技术图片

深度优先算法结合广度优先算法获取物体全部节点关系

深度优先算法是对物体的深度上进行的遍历,广度优先算法是对物体广度上的遍历,若是当咱们想要获得物体的层级关系(如:文件件的全部层级关系,3D 人物的骨骼关键关系等)时,咱们能够将深度优先结合广度优先便可获得整个层级关系——经过深度优先遍历获取获得每一个节点的深度信息,经过广度优先遍历获取到每一个节点的广度信息。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 获取全部关键
/// </summary>
public class ListOfJoints : MonoBehaviour
{
    public Transform HumModel;
    int numCount = 0;
    List<Transform> BreadthFirstList = new List<Transform>();
    Dictionary<Transform, int> BreathFirstDic = new Dictionary<Transform, int>();
    List<Transform> DepthFirstList = new List<Transform>();
    IEnumerator Start()
    {
        yield return new WaitForEndOfFrame();
        DepthFirst_0(HumModel);
        BreadthFirst_0(HumModel);
        yield return new WaitForEndOfFrame();
        foreach (var item in DepthFirstList)
        {
            if (BreathFirstDic.ContainsKey(item))
            {
                string str = "";
                for (int i = 0; i < BreathFirstDic[item]; i++)
                {
                    str += "           ";
                }
                Debug.Log(str + item);
            }
        }
    }
    void BreadthFirst_0(Transform tran)
    {
        List<Transform> joinsList = new List<Transform>();
        foreach (Transform itemJoins in HumModel)
        {
            joinsList.Add(itemJoins);
        }
        BreadthFirst_1(joinsList);
    }
    void BreadthFirst_1(List<Transform> joins)
    {
        numCount++;//层数
        List<Transform> joinsChildListss = new List<Transform>();
        foreach (Transform item in joins)//打印子物体
        {
            BreadthFirstList.Add(item);
            BreathFirstDic.Add(item, numCount);
            if (item.childCount != 0)
            {
                foreach (Transform itemss in item)
                {
                    joinsChildListss.Add(itemss);
                }
            }
        }
        if (joinsChildListss != null && joinsChildListss.Count != 0)
            BreadthFirst_1(joinsChildListss);
    }
    void DepthFirst_0(Transform tran)
    {
        foreach (Transform item in tran)
        {
            DepthFirstList.Add(item);
            if (item.childCount != 0)
            {
                DepthFirst_0(item);
            }
        }
    }


}

技术图片


以上是关于深度优先及广度优先在Unity中的应用的主要内容,如果未能解决你的问题,请参考以下文章

树二叉树遍历算法(深度优先广度优先遍历,前序中序后序层次)及Java实现

基本算法——深度优先搜索(DFS)和广度优先搜索(BFS)

广度优先(bfs)和深度优先搜索(dfs)的应用实例

七十九深度和广度优先搜索算法

爬了个爬性能相关 及 深度优先与广度优先

初始继承之顺序/深度优先及广度优先