为NGUI panel 添加 sorting layer

2015年01月26日 13:41 0 点赞 0 评论 更新于 2025-11-21 15:30

之前看到有人实现了为NGUI Panel添加Sorting Layer的功能,由于我自己当时也不会做,所以现在将其分享给大家。通过这种方式,NGUI和Unity 2D可以完全融合在一起,并且层次关系能够任意设置。

实现步骤

前提条件

NGUI的版本为3.6.8,以下是具体需要添加的代码及位置。

1. 修改 UIDrawCall.cs 文件

1.1 约109行处添加属性

UIDrawCall.cs 文件的约109行处,添加以下代码,用于处理渲染器的排序顺序和排序层名称:

/// <summary>
/// Renderer's sorting order, to be used with Unity's 2D system.
/// </summary>
public int sortingOrder
{
get { return (mRenderer != null) ? mRenderer.sortingOrder : 0; }
set { if (mRenderer != null && mRenderer.sortingOrder != value) mRenderer.sortingOrder = value; }
}

// added by Clark
public string sortingLayerName
{
get { return (mRenderer != null) ? mRenderer.sortingLayerName : "default"; }
set
{
if (mRenderer != null && mRenderer.sortingLayerName != value)
{
mRenderer.sortingLayerName = value;
#if UNITY_EDITOR
UnityEditor.EditorUtility.SetDirty(gameObject);
#endif
}
}
}
// added end by Clark

1.2 约712行处修改 Create 方法

在约712行处,修改 Create 方法,添加对排序层名称的设置:

/// <summary>
/// Create a new draw call, reusing an old one if possible.
/// </summary>
static UIDrawCall Create (string name, UIPanel pan, Material mat, Texture tex, Shader shader)
{
UIDrawCall dc = Create(name);
dc.gameObject.layer = pan.cachedGameObject.layer;
dc.baseMaterial = mat;
dc.mainTexture = tex;
dc.shader = shader;
dc.renderQueue = pan.startingRenderQueue;
dc.sortingOrder = pan.sortingOrder;
// added by Clark
dc.sortingLayerName = pan.sortingLayerName;
// added end by Clark
dc.manager = pan;
return dc;
}

2. 修改 UIPanel.cs 文件

2.1 约130行处添加字段

在约130行处,添加一个用于存储排序层名称的字段:

// Clipping rectangle
[HideInInspector][SerializeField] UIDrawCall.Clipping mClipping = UIDrawCall.Clipping.None;
[HideInInspector][SerializeField] Vector4 mClipRange = new Vector4(0f, 0f, 300f, 200f);
[HideInInspector][SerializeField] Vector2 mClipSoftness = new Vector2(4f, 4f);
[HideInInspector][SerializeField] int mDepth = 0;
[HideInInspector][SerializeField] int mSortingOrder = 0;
// added by Clark
[HideInInspector][SerializeField] string mSortingLayerName;
// added end by Clark

2.2 约252行处添加属性

在约252行添加 sortingOrdersortingLayerName 属性:

public int sortingOrder
{
get
{
return mSortingOrder;
}
set
{
if (mSortingOrder != value)
{
mSortingOrder = value;
#if UNITY_EDITOR
NGUITools.SetDirty(this);
#endif
UpdateDrawCalls();
}
}
}

// added by Clark
public string sortingLayerName
{
get { return mSortingLayerName; }
set
{
if (mSortingLayerName != value)
{
mSortingLayerName = value;
#if UNITY_EDITOR
NGUITools.SetDirty(this);
#endif
UpdateDrawCalls();
}
}
}
// added end by Clark

2.3 约1432行处修改 UpdateDrawCalls 方法

在约1432行的 UpdateDrawCalls 方法中,添加对排序层名称的设置:

for (int i = 0; i < drawCalls.Count; ++i)
{
UIDrawCall dc = drawCalls[i];
Transform t = dc.cachedTransform;
t.position = pos;
t.rotation = rot;
t.localScale = scale;
dc.renderQueue = (renderQueue == RenderQueue.Explicit) ? startingRenderQueue : startingRenderQueue + i;
dc.alwaysOnScreen = alwaysOnScreen &&
(mClipping == UIDrawCall.Clipping.None || mClipping == UIDrawCall.Clipping.ConstrainButDontClip);
dc.sortingOrder = mSortingOrder;
// added by Clark
dc.sortingLayerName = mSortingLayerName;
// added end by Clark
}

3. 修改 UIPanelInspector.cs 文件

3.1 约9行处添加命名空间引用

在约9行处添加必要的命名空间引用:

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
// added by Clark
using System;
using System.Reflection;
using UnityEditorInternal;
// added end by Clark

3.2 约39行处添加字段

在约39行处添加一个用于存储排序层名称数组的字段:

UIWidget.Pivot mDragPivot = UIWidget.Pivot.Center;
GUIStyle mStyle0 = null;
GUIStyle mStyle1 = null;
// added by Clark
string[] sortingLayerNames;
// added end by Clark

3.3 约49行处修改 OnEnable 方法

在约49行的 OnEnable 方法中,初始化排序层名称数组:

protected override void OnEnable ()
{
base.OnEnable();
mPanel = target as UIPanel;
// added by Clark
sortingLayerNames = GetSortingLayerNames();
// added end by Clark
}

3.4 约574行处添加排序层选择界面

在约574行添加排序层选择界面:

GUI.changed = false;
int so = EditorGUILayout.IntField("Sort Order", mPanel.sortingOrder, GUILayout.Width(120f));
if (GUI.changed) mPanel.sortingOrder = so;
// added by Clark
int sortingLayerIndex = GetSortingLayerIndex(mPanel.sortingLayerName);
int newSortingLayerIndex = EditorGUILayout.Popup("Sorting Layer", sortingLayerIndex, sortingLayerNames);
if (sortingLayerIndex != newSortingLayerIndex)
{
mPanel.sortingLayerName = sortingLayerNames[newSortingLayerIndex];
}
// added end by Clark

3.5 约785行处添加辅助方法

在文件最后(约785行)添加两个辅助方法,用于获取排序层名称数组和排序层索引:

// added by Clark
string[] GetSortingLayerNames()
{
Type t = typeof(InternalEditorUtility);
PropertyInfo prop = t.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
return (string[])prop.GetValue(null, null);
}

int GetSortingLayerIndex(string layerName)
{
for (int i = 0; i < sortingLayerNames.Length; i++)
{
if (sortingLayerNames[i] == layerName)
{
return i;
}
}
return 0;
}
// added end by Clark

通过以上步骤,你就可以为NGUI Panel添加Sorting Layer,实现NGUI与Unity 2D的融合以及层次关系的任意设置。

作者信息

feifeila

feifeila

共发布了 3994 篇文章