今回はUnityのキャンバスやUI要素の表示順序を変えてみたいと思います。
複数のキャンバスやUI要素がある時にその表示順を変更したいことがあります。
例えばカードゲームでドラッグしてドロップしたカードを一番手前に表示したい時等です。
Canvasの表示順を変える
まずは複数のCanvasが存在する場合に特定のCanvasを前面に押し出したい時の変更方法です。
以下のように2つのCanvasとその子にPanelを配置し、さらにPanelの子にTextを配置します。
最初のCanvasの子のテキストにはA、B、C、Dを入力します。
一つ目のキャンバスは以下のような感じで重なるように各パネルを移動させます。
次のCanvasの子のテキストには1、2、3、4を入力します。
二つ目のキャンバスは以下のような感じで重なるように各パネルを移動させます。
さらに、二つのCanvasの子が重なるように二つ目のCanvasの子の各パネルを移動して一つ目のキャンバスの要素に重なるようにします。
ここで、1や2が所属するCanvasのインスペクタでCanvasコンポーネントのSort Orderを1にしてみます。
すると以下のように1や2のCanvasの要素が前面に表示されるようになります。
CanvasコンポーネントのSort Orderの値が並べ替えの順序を設定する数値で、他の値より大きい値を設定すると前面に表示されます。
CanvasコンポーネントのRender ModeはどれでもSort Orderの値が大きい方が前面にくるので、例えばWorld Spaceにしてワールドの位置(3D空間上)がカメラから他のCanvasよりも遠くにあった場合でも、そのCanvasが前面に表示されるようになります。
AやBのCanvasのModeをWorld SpaceにしてOrder in Layer(World Spaceの場合はSort OrderではなくOrder in Layer)は0にし、
1や2のCanvasのModeをWorld SpaceにしてPos Zの値を大きくして、カメラから他のCanvasより遠ざけ、Order in Layerは1にすると、
以下のように、カメラから遠い1や2のCanvasの方が前面に表示されるようになります。
ゲーム中にCanvasの表示順序を変更する時はCanvasコンポーネントのsortOrderの値を表示したい順序の数値に変更するだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; public class ChangeTheDisplayOrderOfCanvas : MonoBehaviour { private Canvas canvas; // Start is called before the first frame update void Start() { canvas = GetComponent<Canvas>(); canvas.sortingOrder = 1; } } |
上のスクリプトをどちらかのCanvasに取り付ければそのCanvasのSort Orderが1に設定されるので、その値より小さいSort Orderを持つCanvasより前面に表示されます。
このスクリプトではゲームオブジェクトが登場した時にSort Orderを1にしていますが、前面にしたいタイミングで行うようにすれば特定のカードを前面に表示するということが出来ます(例えばドラッグ後にドロップした時)。
同じキャンバスの子のヒエラルキーの表示順を変える
先ほどはCanvas毎の表示順を変えましたが、Canvasの子の要素の表示順を変えたい場合もあります。
Canvasの子の要素の表示順はヒエラルキーの順番なので、順番を変更すると表示順が変わります。
先ほどのAやBが所属するCanvasでBのPanelをドラッグしてAの上に持っていくとBが一番後ろになり、その後Aになります。
以下が最初の状態。
次がBのPanelをAのPanelの上にくるようにドラッグした状態。
パネルの順序を変えると表示される順序も変わっています。
この順序をスクリプトから変更するには以下のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; public class ChangeTheDisplayOrderOfPanel : MonoBehaviour { // Start is called before the first frame update void Start() { // ヒエラルキーで一番上に移動し、一番後ろに表示される transform.SetAsFirstSibling(); // ヒエラルキーで一番下に移動し、前面に表示される //transform.SetAsLastSibling(); // ヒエラルキーの順番を設定する //transform.SetSiblingIndex(1); } } |
TransformのSetAsFirstSiblingメソッドを使用すると今いる自分の階層の一番上に移動して、一番後ろに表示されます。
TransformのSetAsLastSiblingメソッドを使用すると今いる自分の階層の一番下に移動して、一番手前に表示されます。
TransformのSetSiblingIndexメソッドを使用すると引数で与えた数の順番に移動します。0番目が一番上で、それ以降は一番上からの位置になります。
レンダラーの表示順を変える
レンダラーを持つゲームオブジェクトの表示順もRendererのsortingOrderの値を変更すると変えられます(まったく同じ形状で同じ位置にあるゲームオブジェクトだとわかりやすいかも?)。
2DのSpriteはSpriteRendererコンポーネントを持ちますが、Rendererクラスを継承しているので同じように以下のスクリプトを使えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; public class ChangeTheDisplayOrderOfRenderer : MonoBehaviour { private Renderer rend; // Start is called before the first frame update void Start() { rend = GetComponent<Renderer>(); rend.sortingOrder = 1; } } |
複数の部品に分かれたスプライトで、一人のキャラクターを構成するなどの場合はSortingGroupコンポーネントを使ってください(一人のキャラクターパーツをまとめる)。
終わりに
自作のタイピングゲームでキャンバスの表示順を変えることがあったのでそれを元に記事にしました。
2Dでなく3D上のUIにも使えるのは結構便利かも?(‘ω’)