如果说,
节点可以自带一个是否被遍历的描述字段;
或外部有一个dic存储已经被遍历过的节点的;
那么都很好实现没什么好说的。
下面是一种不需要上述两种操作的遍历方式,有点巧妙
直接上代码
static Stack<Transform> m_transStack = new Stack<Transform>();
public static Transform GetTrans(Transform parentTrans, string needTransName)
{
if (parentTrans == null || string.IsNullOrEmpty(needTransName))
{
return parentTrans;
}
m_transStack.Clear();
m_transStack.Push(parentTrans);
Transform trans = null;
while (m_transStack.Count > 0)
{
trans = m_transStack.Pop();
var cTrans = trans.Find(needTransName);
if (cTrans != null)
{
return cTrans;
}
for (int i = trans.childCount - 1; i >= 0; i--)
{
m_transStack.Push(trans.GetChild(i));
}
}
return null;
}
上面代码从的事情就是从指定的父节点开始,深度优先去找名字为needTransName的节点。
巧妙的地方在于,
当节点从栈pop出来之后,直接把该节点的所有子节点倒序push到栈中。
这样处理为什么可以模仿深度优先呢?
第一,正常按照文章开头那两种方式去遍历的话,都是要等到某个节点的所有子节点都被遍历完了,这个节点才能出栈。
但是这里不用,它直接把所有子节点都塞进去了,我一开始乍一看还以为是层次遍历(但要用队列才是层次),其实并不是,
所有节点塞进去就能保证是按深度优先方式遍历了吗?要看顺序。
第二,push的顺序,把某节点所有子节点按倒序push进栈,这样就能保证了深度优先遍历。
上述两点做法的意义在于,遍历一个节点之后,把他之后所有子节点的遍历顺序都决定好(深度优先)放入栈中等待遍历就行。
细细想想会发现很巧妙,所以记录下来。