概要
- Sprite Rendererと通常のMesh Rendererの描画順でハマったのでその備忘録と解決策です
- 解決策だけ知りたい方はMesh RendererにOrder In Layerを設定するまで飛んでください
半透明描画の描画順
Mesh Renderer
まず下記の条件で調べます
- Apple:Render Queue=3000
- Boy:Render Queue=3000
- 位置関係:Boyの方がAppleより手前
次にAppleのRender Queue
を+1して3001にします
すると位置関係を無視して、AppleがBoyの前に描画されます
Sprite Renderer
次にSprite Rendererの場合です
- Apple:Order In Layer=0
- Boy:Order In Layer=0
- 位置関係:Boyの方がAppleより手前
この場合もBoyが手前として描画されます
Appleの方のOrder In Layer
を1に変更します
この場合も位置関係を無視して、AppleがBoyの前に描画されます
Sprite RendererとMesh Rendererを組み合わせた場合
この2つを組み合わせた場合描画順は複雑になります
まず以下のように設定します
表示物 | 表示方法 | |
---|---|---|
Apple | Sprite Renderer | Order In Layer=0 |
Boy | Sprite Renderer | Order In Layer=0 |
Car | Mesh Renderer | Render Queue=3000 |
次に一番奥にあるAppleのOrder In Layerを1に変更します
表示物 | 表示方法 | |
---|---|---|
Apple | Sprite Renderer | Order In Layer=1 |
Boy | Sprite Renderer | Order In Layer=0 |
Car | Mesh Renderer | Render Queue=3000 |
するとAppleはCarより手前に描画されるようになってしまいます
このときCarのRender Queue
を大きくしてもAppleより手前に描画されることはありません
次節で解決方法を紹介します
Mesh RendererにOrder In Layerを設定する
Mesh Rendererにも実はOrder In Layerのパラメータが存在します
しかし、通常のGUIからは操作できないようになっています。
そこで、Editor拡張を追加することで操作を可能にします
using UnityEngine;
using UnityEditor;
using System.Linq;
using System;
[CustomEditor(typeof(MeshRenderer))]
public class MyMeshRendererInspector : Editor
{
Editor defaultEditor;
private void OnEnable()
{
this.defaultEditor = Editor.CreateEditor(targets, Type.GetType("UnityEditor.MeshRendererEditor, UnityEditor"));
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.BeginHorizontal();
// sorting order
var sortOrderProperty = serializedObject.FindProperty("m_SortingOrder");
sortOrderProperty.intValue = EditorGUILayout.IntField("Sort Order", sortOrderProperty.intValue);
// sorting layer
var layerIDProperty = serializedObject.FindProperty("m_SortingLayerID");
var index = System.Array.FindIndex(SortingLayer.layers, layer => layer.id == layerIDProperty.intValue);
index = EditorGUILayout.Popup(index, (from layer in SortingLayer.layers select layer.name).ToArray());
layerIDProperty.intValue = SortingLayer.layers[index].id;
EditorGUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties();
this.defaultEditor.OnInspectorGUI();
}
}
ソースコードはこちらを参考にさせていただきました
MeshRendererでSortingLayerIDやOrderInLayerを変更する拡張スクリプト
このスクリプトをプロジェクト内に導入することでMesh RendererのOrder In Layerを設定することが可能になります
この機能を使って、CarのOrder In Layerを設定します
表示物 | 表示方法 | |
---|---|---|
Apple | Sprite Renderer | Order In Layer=1 |
Boy | Sprite Renderer | Order In Layer=0 |
Car | Mesh Renderer | Render Queue=3000 Order In Layer=1 |
まとめ
- 描画順制御は一度やりだすとあらゆるオブジェクトの描画順を管理しなければならないため、極力描画順制御しないつくりを目指すことをお勧めします
- 特に今回のようにSprite RendererとMesh Rendererが入り混じったシーンの場合、描画順制御の難易度が上がります