游戲中,界面上有些按鈕之上需要放置一個特效,或者有些區域顯示比如image上顯示一個特效,這時候如果再打開一個UI,我們需要讓新的UI顯示在特效上層,而不是被特效遮擋,這是就需要設置特效的渲染順序。
設置特效的order in layer,新版的unity中,particle system可以直接設置render的order,但是特效中有些是使用particle system做的,有些又是直接用的圖像動畫等等,而類似MeshRender的order in layer是不能在編輯器直接設置的,
所以靠手工設置是不現實的,需要用腳本設置。
代碼:

// 深度遍歷設置所有 Render 的 SortingLayer public static void setRenderSortingLayerByActor(GameObject actor, int order, bool isRecursion) { if (null != actor) { UtilApi.setSpriteRenderSortingLayerByActor(actor, order); UtilApi.setParticleSystemSortingLayerByActor(actor, order); UtilApi.setMeshRenderSortingLayerByActor(actor, order); int childCount = actor.transform.childCount; int idx = 0; Transform childTrans = null; if (isRecursion) { for (idx = 0; idx < childCount; ++idx) { childTrans = actor.transform.GetChild(idx); UtilApi.setRenderSortingLayerByActor(childTrans.gameObject, order, isRecursion); } } } } static public void setSpriteRenderSortingLayerByActor(UnityEngine.GameObject actor, int order) { if (null != actor) { SpriteRenderer render = null; render = actor.GetComponent<SpriteRenderer>(); UtilApi.setSpriteRenderSortingLayerBySpriteRenderer(render, order); } } /** * @brief unity渲染層級關系小結 * @ref http://blog.csdn.net/meegomeego/article/details/42060389 */ // 可以在編輯器中設置 static public void setSpriteRenderSortingLayerBySpriteRenderer(SpriteRenderer render, int order) { if (null != render && render.sortingOrder != order) { render.sortingOrder = order; } } static public void setParticleSystemSortingLayerByActor(UnityEngine.GameObject actor, int order) { if (null != actor) { ParticleSystem particleSystem = null; particleSystem = actor.GetComponent<ParticleSystem>(); UtilApi.setParticleSystemSortingLayer(particleSystem, order); } } // 不能在編輯器中設置 static public void setParticleSystemSortingLayer(ParticleSystem particleSystem, int order) { if (null != particleSystem) { Renderer render = particleSystem.GetComponent<Renderer>(); if (null != render && render.sortingOrder != order) { render.sortingOrder = order; } } } static public void setMeshRenderSortingLayerByActor(UnityEngine.GameObject actor, int order) { if (null != actor) { UnityEngine.MeshRenderer meshRenderer = null; meshRenderer = actor.GetComponent<UnityEngine.MeshRenderer>(); UtilApi.setMeshRenderSortingLayer(meshRenderer, order); } } // 不能在編輯器中設置 static public void setMeshRenderSortingLayer(UnityEngine.MeshRenderer meshRenderer, int order) { if (null != meshRenderer && meshRenderer.sortingOrder != order) { meshRenderer.sortingOrder = order; } }
使用時:UtilApi.setRenderSortingLayerByActor(this.mSelfGo, 1, true); 參數中,this.mSelfGo就是特效實例化的父節點,1就是設置的order in layer,因為ui的order默認都是0,所以這個設為1,true循環設置子節點
按理說這個order in layer設置為0我覺得應該也是正確的,但在我的游戲中設置為0就無法顯示特效,我確實沒有理解。
我的游戲結點如圖:
ef_quan2all就是我的特效實例,按照這個順序應該也是最后渲染的,不明白設置為0為何就不顯示,不知有人能否告知。
order in layer設為1后,特效顯示了,但是后面出現了一個問題,如果這時打開一個其他的UI,特效會遮擋這個UI,坑爹。。
這時就要使出殺手鐧了,因為UI上類似Image或者Button是無法設置order in layer的,所以要給這個被遮擋的UI添加一個Canvas,Canvas可以設置order,那么將其設置為2,比特效的大,不錯,可以顯示了,但是又出現一個問題,這個界面上的按鈕事件被攔截了,擦。。。
又一招出手,給其再設置一個Graphic Raycster,參數如下
終於完美了。。,既可以顯示特效,還不會遮擋UI
至此有個問題,如果界面很多都需要設置上述的canvas,那就需要自己實現一個管理類,給每個ui設置它的order,不過canvas會影響合並批次,所以不能有太多,自己權衡。