NGUI处理特效显示和面板显示夹层问题

Posted AlanE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NGUI处理特效显示和面板显示夹层问题相关的知识,希望对你有一定的参考价值。

NGUI相当不错,但是有一点比较纠结的就是面板上显示特效的时候,你会发现要么盖住特效,要么面板永远无法盖住特效。很多人说改renderqueue,然后就能显示了,然后下面一堆楼主给力。。。。呵呵。 
       
先从原理上解释吧,NGUI是通过调整renderqueue来显示不同层,然后它的shader是不写入z值的,然后特效刚好也是不写入z值的,所以你 
要控制特效和UI的关系,确实只能通过renderqueue.但是如果你只是单纯让renderqueue非常大,那么特效就会永远在面板之上。 
      如果你想要两个面板夹住特效,那么就需要看NGUI源代码了。 
      这里希望大家自己去看一下,我直接贴上修改方案: 
if (this.widgetInFrontOfMe != null && this.widgetInFrontOfMe.drawCall != null) { 
             int rq = this.widgetInFrontOfMe.drawCall.renderQueue + 1; 
             Debug.Log(rq); 
             foreach (Material material in m_renderer.materials) { 
                 if(material.renderQueue != rq) 
                 { 
                     material.renderQueue = rq; 
                 } 
             } 
         } 


首先这段代码就是将特效的renderqueu调整成你想要放置的物体的前面。然后你如果在Update()或者LateUpdate()中执行这 
段代码,你会发现它工作的不错,就是偶尔会闪一下,这是因为这段代码先更新了,然后NGUI才更新,所以导致滞后一帧。对于我这种完美主义者来说,这是不 
能接受的。所以我修改了UIPanel的源代码,然里面全部更新完毕后,再去调用这个函数。哈哈,一切都非常完美。 
完整代码如下:using UnityEngine; 
 using System.Collections.Generic; 
  
 public class UISortBehavior : MonoBehaviour 
 { 
     public UIPanel panel; 
     public UIWidget widgetInFrontOfMe; 
     public bool AddQueue=true; 
     
     [System.NonSerialized] 
     Renderer m_renderer; 
     
     void Awake() { 
         m_renderer = this.renderer; 
     } 
  
     public void initPanel(UIPanel p) 
     { 
         panel = p; 
     } 
  
     void Start() 
     { 
         panel.addUISort (this); 
     } 
  
     public void UpdateSortUI() 
     { 
         if (this.widgetInFrontOfMe != null && this.widgetInFrontOfMe.drawCall != null) { 
             int rq = this.widgetInFrontOfMe.drawCall.renderQueue + 1; 
             if(!AddQueue) 
                 rq -= 2; 
             foreach (Material material in m_renderer.materials) { 
                 if(material.renderQueue != rq) 
                 { 
                     material.renderQueue = rq; 
                 } 
             } 
         } 
     } 
  
     void OnDestroy() 
     { 
         if(panel != null) 
             panel.removeUISort (this); 
     } 
  



当然UIPanel中也要修改: 
void LateUpdate () 
     { 
         if (mUpdateFrame != Time.frameCount) 
         { 
             mUpdateFrame = Time.frameCount; 
  
             // Update each panel in order 
             for (int i = 0; i < list.size; ++i) 
                 list.UpdateSelf(); 
  
             int rq = 3000; 
  
             // Update all draw calls, making them draw in the right order 
             for (int i = 0; i < list.size; ++i) 
             { 
                 UIPanel p = list.buffer
  
                 if (p.renderQueue == RenderQueue.Automatic) 
                 { 
                     p.startingRenderQueue = rq; 
                     p.UpdateDrawCalls(); 
                     //rq += p.drawCalls.size; 
                     rq += p.drawCalls.size * 2; 
                 } 
                 else if (p.renderQueue == RenderQueue.StartAt) 
                 { 
                     p.UpdateDrawCalls(); 
                     if (p.drawCalls.size != 0) 
                         rq = Mathf.Max(rq, p.startingRenderQueue + p.drawCalls.size * 2); 
                         //rq = Mathf.Max(rq, p.startingRenderQueue + p.drawCalls.size); 
                 } 
                 else // Explicit 
                 { 
                     p.UpdateDrawCalls(); 
                     if (p.drawCalls.size != 0) 
                         rq = Mathf.Max(rq, p.startingRenderQueue + 2); 
                         //rq = Mathf.Max(rq, p.startingRenderQueue + 1); 
                 } 
                 p.updateUISort(); 
             } 
  
  
         } 
     } 
  
List<UISortBehavior> container = new List<UISortBehavior>(); 
  
     public void addUISort(UISortBehavior uiSort) 
     { 
         if(container.Contains(uiSort)) 
         { 
             return; 
         } 
         container.Add (uiSort); 
     } 
  
     public void removeUISort(UISortBehavior uiSort) 
     { 
         container.Remove (uiSort); 
     } 
  
     public void updateUISort() 
     { 
         for(int i = 0; i < container.Count; i++) 
         { 
             container.UpdateSortUI(); 
         } 
     } 

void UpdateDrawCalls () 
     { 
         Transform trans = cachedTransform; 
         bool isUI = usedForUI; 
  
         if (clipping != UIDrawCall.Clipping.None) 
         { 
             drawCallClipRange = finalClipRegion; 
             drawCallClipRange.z *= 0.5f; 
             drawCallClipRange.w *= 0.5f; 
         } 
         else drawCallClipRange = Vector4.zero; 
  
         // Legacy functionality 
         if (drawCallClipRange.z == 0f) drawCallClipRange.z = Screen.width * 0.5f; 
         if (drawCallClipRange.w == 0f) drawCallClipRange.w = Screen.height * 0.5f; 
  
         // DirectX 9 half-pixel offset 
         if (halfPixelOffset) 
         { 
             drawCallClipRange.x -= 0.5f; 
             drawCallClipRange.y += 0.5f; 
         } 
  
         Vector3 pos; 
  
         // We want the position to always be on even pixels so that the 
         // panel‘s contents always appear pixel-perfect. 
         if (isUI) 
         { 
             Transform parent = cachedTransform.parent; 
             pos = cachedTransform.localPosition; 
  
             if (parent != null) 
             { 
                 float x = Mathf.Round(pos.x); 
                 float y = Mathf.Round(pos.y); 
  
                 drawCallClipRange.x += pos.x - x; 
                 drawCallClipRange.y += pos.y - y; 
  
                 pos.x = x; 
                 pos.y = y; 
                 pos = parent.TransformPoint(pos); 
             } 
             pos += drawCallOffset; 
         } 
         else pos = trans.position; 
  
         Quaternion rot = trans.rotation; 
         Vector3 scale = trans.lossyScale; 
  
         for (int i = 0; i < drawCalls.size; ++i) 
         { 
             UIDrawCall dc = drawCalls.buffer
  
             Transform t = dc.cachedTransform; 
             t.position = pos; 
             t.rotation = rot; 
             t.localScale = scale; 
  
             //dc.renderQueue = (renderQueue == RenderQueue.Explicit) ? startingRenderQueue : startingRenderQueue + i; 
             dc.renderQueue = (renderQueue == RenderQueue.Explicit) ? startingRenderQueue : startingRenderQueue + i * 2; 
             dc.alwaysOnScreen = alwaysOnScreen && 
                 (mClipping == UIDrawCall.Clipping.None || mClipping == UIDrawCall.Clipping.ConstrainButDontClip); 
 #if !UNITY_3_5 && !UNITY_4_0 && !UNITY_4_1 && !UNITY_4_2 
             dc.sortingOrder = mSortingOrder; 
 #endif 
         } 
     }

以上是关于NGUI处理特效显示和面板显示夹层问题的主要内容,如果未能解决你的问题,请参考以下文章

csharp ScreenBase是Unity UI面板的基类。它处理转换,在屏幕显示和延迟之前和之后添加任务。它德

Unity NGUI和UGUI与模型特效的层级关系

NGUI_Depth

NGUI中穿插粒子或者mesh渲染层级

NGUI里使用UIDragDropItem的OnDragDropRelease时,surface总是显示UI Root的问题解决

ngui处理不规则按钮点击