NGUI自动设置 Panel 深度、自动设置UIWidget(Sprite/Label等)深度(按照Hierarchy 顺序从上到下 Depth 递增)
2016-09-05 01:54
344 查看
最开始使用 NGUI的时候,一直在接收NGUI的各种设定。后面项目用UGUI,相比NGUI更方便些,但是可控性却少了,现在又开始新项目,重归NGUI。
但是又开始纠结Panel的深度管理。
项目中设计的是所有界面共用一个 UIRoot,就不用考虑 Camera的Depth问题。剩下的就是Panel的深度问题。
比如主界面设置 Depth 为1,那么背包界面自然设置为2,然后道具信息界面设置为3?
这是不确定的,因为背包界面可能有其它的子 Panel 。比如道具滑动页。
如果是一个人制作的话,会考虑到。但是项目中一般是多人协作,沟通起来会产生问题。
所以还是尝试在游戏中自动设置Panel的Depth。
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
最开始尝试在WindowManager中,每打开一个窗口,都遍历UIPanel,设置Depth,但是这样的话,动态加载的界面又不能照顾到。
然后在WindowManager的Update函数中,去遍历设置,这样是Ok的。
void Update()
{
Profiler.BeginSample("WindowManager Depth");
ProfilerTimer.BeginSample("WindowManager Depth");
int tmpNodeCount = GetNodeCount(mTransformUIRoot);
ProfilerTimer.EndSample();
Profiler.EndSample();
if (mChildrenCount !=tmpNodeCount )
{
//获取所有的Panel
UIPanel[] tmpPanels = mTransformUIRoot.GetComponentsInChildren<UIPanel>(true);
//遍历Panel,Depth 递增
for (int i = 0; i < tmpPanels.Length; i++)
{
tmpPanels[i].depth = mWindowPanelDepthBegin + i;
}
}
mWindowPanelDepthBegin = 1;
mChildrenCount = tmpNodeCount;
}
int GetNodeCount(Transform varTransform)
{
int tmpCount = varTransform.childCount;
for(int i=0;i<varTransform.childCount;i++)
{
tmpCount += varTransform.GetChild(i).childCount;
}
return tmpCount;
}
效率上其实并没有什么问题。但是心有总有疙瘩,而且这样没有通用性。
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
最后还是选择修改 UIPanel,在OnStart中,遍历修改Depth
/// <summary>
/// Layer is used to ensure that if it changes, widgets get moved as well.
/// </summary>
protected override void OnStart ()
{
mLayer = mGo.layer;
//获取所有的Panel
UIPanel[] tmpPanels = transform.root.GetComponentsInChildren<UIPanel>(true);
//遍历Panel,Depth 递增
for (int i = 0; i < tmpPanels.Length; i++)
{
tmpPanels[i].depth = 1 + i;
}
}
按照这种设置的话,在Hierarchy 顺序从上到下 ,Depth是递增的。在编辑器状态下也会执行。
又想到了其它问题。
在编辑器状态下,每次新建 UIPanel后都会自动排序。但是如果UIPanel的GameObject被拖动,那排序在编辑器状态下就失效了。所以,为了确保这种情况下也可以自动排序,就在 Update中也进行排序操作吧。
在UIPanel中添加下面代码。
protected override void OnUpdate()
{
base.OnUpdate();
#if UNITY_EDITOR
if(Application.isPlaying==false)
{
//获取所有的Panel
UIPanel[] tmpPanels = transform.root.GetComponentsInChildren<UIPanel>(true);
//遍历Panel,Depth 递增
for (int i = 0; i < tmpPanels.Length; i++)
{
tmpPanels[i].depth = 1 + i;
}
}
#endif
}这样不管怎么拖动,Panel都会自动设置了。
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
Panel的自动排序设置好了,下面来看下 Sprite、Label这些 UIWidget 的自动排序。
因为对于UIWidget来说,都是以Panel 为父节点的。所以这里的UIWidget排序都是对一个Panel下的UIWidget排序。
而且一般我们做好Prefab之后,很少在游戏中去改变 UIWidget的Depth。一般没有这个必要。
所以对于UIWidget,我这里只做编辑器状态下的排序。
修改 UIWidget 代码
/// <summary>
/// Ensure we have a panel to work with.
/// </summary>
protected override void OnUpdate ()
{
if (panel == null) CreatePanel();
#if UNITY_EDITOR
else if (!mPlayMode) ParentHasChanged();
if(Application.isPlaying==false)
{
//获取所有的UIWidget
Transform tmpRootPanel = GetRootPanel(transform);
UIWidget[] tmpWidgets = tmpRootPanel.GetComponentsInChildren<UIWidget>(true);
//遍历UIWidget,Depth 递增
for (int i = 0; i < tmpWidgets.Length; i++)
{
tmpWidgets[i].depth = 1 + i;
}
}
#endif
}
Transform GetRootPanel(Transform varTransform)
{
Transform tmpParent=varTransform.parent;
if(tmpParent!=null)
{
if(tmpParent.GetComponent<UIPanel>()!=null)
{
return tmpParent;
}
else
{
tmpParent = GetRootPanel(tmpParent);
}
return tmpParent;
}
else
{
return varTransform;
}
}
效果是这样
现在应该已经可以不用在编辑器调整 Depth了,那就在编辑器中隐藏 Depth的设置按钮吧
首先是Panel的,修改 UIPanelInspector 代码,注释掉Depth 设置按钮区域
protected override bool ShouldDrawProperties ()
{
float alpha = EditorGUILayout.Slider("Alpha", mPanel.alpha, 0f, 1f);
if (alpha != mPanel.alpha)
{
NGUIEditorTools.RegisterUndo("Panel Alpha", mPanel);
mPanel.alpha = alpha;
}
//GUILayout.BeginHorizontal();
//{
// EditorGUILayout.PrefixLabel("Depth");
// int depth = mPanel.depth;
// if (GUILayout.Button("Back", GUILayout.Width(60f))) --depth;
// depth = EditorGUILayout.IntField(depth, GUILayout.MinWidth(20f));
// if (GUILayout.Button("Forward", GUILayout.Width(68f))) ++depth;
// if (mPanel.depth != depth)
// {
// NGUIEditorTools.RegisterUndo("Panel Depth", mPanel);
// mPanel.depth = depth;
// if (UIPanelTool.instance != null)
// UIPanelTool.instance.Repaint();
// if (UIDrawCallViewer.instance != null)
// UIDrawCallViewer.instance.Repaint();
// }
//}
//GUILayout.EndHorizontal();
然后是UIWidget的,修改UIWidgetInspector,注释掉 Depth 设置区域
/// <summary>
/// Draw widget's depth.
/// </summary>
static void DrawDepth (SerializedObject so, UIWidget w, bool isPrefab)
{
if (isPrefab) return;
GUILayout.Space(2f);
//GUILayout.BeginHorizontal();
//{
// EditorGUILayout.PrefixLabel("Depth");
// if (GUILayout.Button("Back", GUILayout.MinWidth(46f)))
// {
// foreach (GameObject go in Selection.gameObjects)
// {
// UIWidget pw = go.GetComponent<UIWidget>();
// if (pw != null) pw.depth = w.depth - 1;
// }
// }
// NGUIEditorTools.DrawProperty("", so, "mDepth", GUILayout.MinWidth(20f));
// if (GUILayout.Button("Forward", GUILayout.MinWidth(60f)))
// {
// foreach (GameObject go in Selection.gameObjects)
// {
// UIWidget pw = go.GetComponent<UIWidget>();
// if (pw != null) pw.depth = w.depth + 1;
// }
// }
//}
//GUILayout.EndHorizontal();
int matchingDepths = 1;
UIPanel p = w.panel;
if (p != null)
{
for (int i = 0, imax = p.widgets.Count; i < imax; ++i)
{
UIWidget pw = p.widgets[i];
if (pw != w && pw.depth == w.depth)
++matchingDepths;
}
}
if (matchingDepths > 1)
{
EditorGUILayout.HelpBox(matchingDepths + " widgets are sharing the depth value of " + w.depth, MessageType.Info);
}
}
就是这样了。
但是又开始纠结Panel的深度管理。
项目中设计的是所有界面共用一个 UIRoot,就不用考虑 Camera的Depth问题。剩下的就是Panel的深度问题。
比如主界面设置 Depth 为1,那么背包界面自然设置为2,然后道具信息界面设置为3?
这是不确定的,因为背包界面可能有其它的子 Panel 。比如道具滑动页。
如果是一个人制作的话,会考虑到。但是项目中一般是多人协作,沟通起来会产生问题。
所以还是尝试在游戏中自动设置Panel的Depth。
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
最开始尝试在WindowManager中,每打开一个窗口,都遍历UIPanel,设置Depth,但是这样的话,动态加载的界面又不能照顾到。
然后在WindowManager的Update函数中,去遍历设置,这样是Ok的。
void Update()
{
Profiler.BeginSample("WindowManager Depth");
ProfilerTimer.BeginSample("WindowManager Depth");
int tmpNodeCount = GetNodeCount(mTransformUIRoot);
ProfilerTimer.EndSample();
Profiler.EndSample();
if (mChildrenCount !=tmpNodeCount )
{
//获取所有的Panel
UIPanel[] tmpPanels = mTransformUIRoot.GetComponentsInChildren<UIPanel>(true);
//遍历Panel,Depth 递增
for (int i = 0; i < tmpPanels.Length; i++)
{
tmpPanels[i].depth = mWindowPanelDepthBegin + i;
}
}
mWindowPanelDepthBegin = 1;
mChildrenCount = tmpNodeCount;
}
int GetNodeCount(Transform varTransform)
{
int tmpCount = varTransform.childCount;
for(int i=0;i<varTransform.childCount;i++)
{
tmpCount += varTransform.GetChild(i).childCount;
}
return tmpCount;
}
效率上其实并没有什么问题。但是心有总有疙瘩,而且这样没有通用性。
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
最后还是选择修改 UIPanel,在OnStart中,遍历修改Depth
/// <summary>
/// Layer is used to ensure that if it changes, widgets get moved as well.
/// </summary>
protected override void OnStart ()
{
mLayer = mGo.layer;
//获取所有的Panel
UIPanel[] tmpPanels = transform.root.GetComponentsInChildren<UIPanel>(true);
//遍历Panel,Depth 递增
for (int i = 0; i < tmpPanels.Length; i++)
{
tmpPanels[i].depth = 1 + i;
}
}
按照这种设置的话,在Hierarchy 顺序从上到下 ,Depth是递增的。在编辑器状态下也会执行。
又想到了其它问题。
在编辑器状态下,每次新建 UIPanel后都会自动排序。但是如果UIPanel的GameObject被拖动,那排序在编辑器状态下就失效了。所以,为了确保这种情况下也可以自动排序,就在 Update中也进行排序操作吧。
在UIPanel中添加下面代码。
protected override void OnUpdate()
{
base.OnUpdate();
#if UNITY_EDITOR
if(Application.isPlaying==false)
{
//获取所有的Panel
UIPanel[] tmpPanels = transform.root.GetComponentsInChildren<UIPanel>(true);
//遍历Panel,Depth 递增
for (int i = 0; i < tmpPanels.Length; i++)
{
tmpPanels[i].depth = 1 + i;
}
}
#endif
}这样不管怎么拖动,Panel都会自动设置了。
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
Panel的自动排序设置好了,下面来看下 Sprite、Label这些 UIWidget 的自动排序。
因为对于UIWidget来说,都是以Panel 为父节点的。所以这里的UIWidget排序都是对一个Panel下的UIWidget排序。
而且一般我们做好Prefab之后,很少在游戏中去改变 UIWidget的Depth。一般没有这个必要。
所以对于UIWidget,我这里只做编辑器状态下的排序。
修改 UIWidget 代码
/// <summary>
/// Ensure we have a panel to work with.
/// </summary>
protected override void OnUpdate ()
{
if (panel == null) CreatePanel();
#if UNITY_EDITOR
else if (!mPlayMode) ParentHasChanged();
if(Application.isPlaying==false)
{
//获取所有的UIWidget
Transform tmpRootPanel = GetRootPanel(transform);
UIWidget[] tmpWidgets = tmpRootPanel.GetComponentsInChildren<UIWidget>(true);
//遍历UIWidget,Depth 递增
for (int i = 0; i < tmpWidgets.Length; i++)
{
tmpWidgets[i].depth = 1 + i;
}
}
#endif
}
Transform GetRootPanel(Transform varTransform)
{
Transform tmpParent=varTransform.parent;
if(tmpParent!=null)
{
if(tmpParent.GetComponent<UIPanel>()!=null)
{
return tmpParent;
}
else
{
tmpParent = GetRootPanel(tmpParent);
}
return tmpParent;
}
else
{
return varTransform;
}
}
效果是这样
现在应该已经可以不用在编辑器调整 Depth了,那就在编辑器中隐藏 Depth的设置按钮吧
首先是Panel的,修改 UIPanelInspector 代码,注释掉Depth 设置按钮区域
protected override bool ShouldDrawProperties ()
{
float alpha = EditorGUILayout.Slider("Alpha", mPanel.alpha, 0f, 1f);
if (alpha != mPanel.alpha)
{
NGUIEditorTools.RegisterUndo("Panel Alpha", mPanel);
mPanel.alpha = alpha;
}
//GUILayout.BeginHorizontal();
//{
// EditorGUILayout.PrefixLabel("Depth");
// int depth = mPanel.depth;
// if (GUILayout.Button("Back", GUILayout.Width(60f))) --depth;
// depth = EditorGUILayout.IntField(depth, GUILayout.MinWidth(20f));
// if (GUILayout.Button("Forward", GUILayout.Width(68f))) ++depth;
// if (mPanel.depth != depth)
// {
// NGUIEditorTools.RegisterUndo("Panel Depth", mPanel);
// mPanel.depth = depth;
// if (UIPanelTool.instance != null)
// UIPanelTool.instance.Repaint();
// if (UIDrawCallViewer.instance != null)
// UIDrawCallViewer.instance.Repaint();
// }
//}
//GUILayout.EndHorizontal();
然后是UIWidget的,修改UIWidgetInspector,注释掉 Depth 设置区域
/// <summary>
/// Draw widget's depth.
/// </summary>
static void DrawDepth (SerializedObject so, UIWidget w, bool isPrefab)
{
if (isPrefab) return;
GUILayout.Space(2f);
//GUILayout.BeginHorizontal();
//{
// EditorGUILayout.PrefixLabel("Depth");
// if (GUILayout.Button("Back", GUILayout.MinWidth(46f)))
// {
// foreach (GameObject go in Selection.gameObjects)
// {
// UIWidget pw = go.GetComponent<UIWidget>();
// if (pw != null) pw.depth = w.depth - 1;
// }
// }
// NGUIEditorTools.DrawProperty("", so, "mDepth", GUILayout.MinWidth(20f));
// if (GUILayout.Button("Forward", GUILayout.MinWidth(60f)))
// {
// foreach (GameObject go in Selection.gameObjects)
// {
// UIWidget pw = go.GetComponent<UIWidget>();
// if (pw != null) pw.depth = w.depth + 1;
// }
// }
//}
//GUILayout.EndHorizontal();
int matchingDepths = 1;
UIPanel p = w.panel;
if (p != null)
{
for (int i = 0, imax = p.widgets.Count; i < imax; ++i)
{
UIWidget pw = p.widgets[i];
if (pw != w && pw.depth == w.depth)
++matchingDepths;
}
}
if (matchingDepths > 1)
{
EditorGUILayout.HelpBox(matchingDepths + " widgets are sharing the depth value of " + w.depth, MessageType.Info);
}
}
就是这样了。
相关文章推荐
- 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- PHP实现在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排列,每一列都按照从上到下递增的顺序排列,请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 剑指offer——题目描述 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数
- 问题描述大概如下:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 二维数组中的查找-在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数
- 在一个二维数组中,每一行都按照从左到右递增的顺序排列,每一列都按照从上到下递增的顺序排列,请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。