【Godot】2Dゲームの描画順の制御方法

# 概要
この記事では、2Dゲーム作成時における描画順の制御方法について説明します。

# z_index を使う方法
z_indexを使用するとお手軽に描画順を制御できます。
z_indexの値が大きいほど手前に描画され、z_indexの値が小さいほど奥に描画されます。
![イラスト2___1280_x_720px_72dpi_121_5__.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/e352d5d6-777d-db7a-f8ef-f87dd02c4c2e.png)


以下、簡単に検証用コードを書きます。

## Spriteを作成
Spriteを作成し、"icon.png" をテクスチャに割り当てます。
![Godot_Engine_-_TestLayer____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/ac473a37-1298-cc9f-fa76-77a721ae4596.png)

そしてノード名を「Godot」に変更して、シーンとして保存します。
![Godot_Engine_-_TestLayer____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/d3e20dad-0832-1871-63cd-f9b33c4f68fa.png)

## Mainシーンを作成
Godotくんを配置する Mainシーンを作成します。
![Godot_Engine_-_TestLayer____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/e49f7eae-020f-8e4c-3c41-3adac6c389a2.png)
2Dシーン(Node2D)を作成して名前を Main に変更します。

## Godotくんを配置するスクリプトを作成
Mainシーンにスクリプトをアタッチして、以下のように記述します

```gd:Main.gd
extends Node2D

# Godotくん
var Godot = preload("res://Godot.tscn")

# 生成カウンタ
var idx = 0

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_accept"):
		# Godotくんを生成
		var gd = Godot.instance()
		
		# 16pxずつオフセットする
		gd.position = Vector2(idx*16, idx*16)
		
		# z_indexを設定
		gd.z_index = idx
		
		# シーンに追加する
		add_child(gd)
		
		# 生成カウンタを増やす
		idx += 1
```

Spaceキーを押すたびに、Godotくんを配置するスクリプトです。
実行すると、後に生成されるほど下に描画されることを確認します。

![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/fb471e94-343d-82d0-3255-9aa1606e78f7.gif)

### z_indexをマイナス方向に増やしてみる
z_indexをマイナス方向に増やすとどうなるかを見てみます。

```gd:Main.gd
extends Node2D

# Godotくん
var Godot = preload("res://Godot.tscn")

# 生成カウンタ
var idx = 0

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_accept"):
		# Godotくんを生成
		var gd = Godot.instance()
		
		# 16pxずつオフセットする
		gd.position = Vector2(idx*16, idx*16)
		
		# z_indexを設定
		gd.z_index = -idx # ※マイナスを設定
		
		# シーンに追加する
		add_child(gd)
		
		# 生成カウンタを増やす
		idx += 1

```

修正箇所は `z_index` を設定しているところで、値をマイナスして反転しています。
これを実行すると後で生成したGodotくんは奥に描画されていることが確認できます。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/11b6f75d-4852-c925-d8b5-0f1d4214160c.gif)

# CanvasLayerで描画順を制御する
`z_index` だけで描画順を制御してもよいですが、背景（奥に置きたい）やUI（手前に表示したい）など、柔軟に描画順を制御するには `CanvasLayer` を使用します。

検証用として、奥に描画する用の画像…… (→ "bg_back.png" として保存)
![bg_back.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/011f8f02-26d7-1f72-fee8-a6fa6ff6ddc1.png)


そして手前に描画する空の画像を追加します。(→ "bg_sky.png" として保存)
![bg_sky.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/1b9d12eb-8bbd-0c11-86ed-d877697a824a.png)


ちなみにこの画像は 
http://o-mega.sakura.ne.jp/product/exelinya.html
からお借りしています。

## 背景画像の登録
`CanvasLayer`を 作成します。
![Godot_Engine_-_TestLayer_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/e96fbb79-2601-9caa-7bb5-be326acb322f.png)

ノード名は「Background」に変更しておきます。
![Godot_Engine_-_TestLayer_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/00cee81f-9fae-41dc-b727-a6ff2bff8e99.png)

インスペクタから `Layer > Layer` の値を "-1" にします。この値は小さいほど画面の奥に描画されます
![Godot_Engine_-_TestLayer_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/3c5d0c51-bcb0-9992-60f7-3a9257eb947e.png)

そして「Background」の下に "bg_back.png" を Spriteとしてぶら下げます。
「Background」を選んだ状態で画像をドラッグ＆ドロップすると登録できます。
![Godot_Engine_-_TestLayer_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/e07fef9e-84da-2423-8d65-d67f2f753069.png)

## 空画像の登録
さらに別の `CanvasLayer` を作成します。
名前は 「Sky」としておきます。
![Godot_Engine_-_TestLayer_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/9b21d34a-6bf4-a417-35f6-a258f0811a95.png)
Layerの値は「1」のままで問題ありません。
![Godot_Engine_-_TestLayer_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/272f5473-c144-6de6-37de-a463f7234f5c.png)

続けて "bg_sky.png" をドラッグ＆ドロップして登録します。
![Godot_Engine_-_TestLayer_-_Main_tscn____.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/0725b92f-cbb5-3820-b876-516d57345214.png)

実行して Spaceキーを連打すると、空の中からGodotくんが登場します。
![shot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43772/a908b154-770a-c0f0-7203-d540708ffcd0.gif)

# まとめ
今回の記事のまとめです。

* `z_index` で描画順を制御できる
  * `z_index` は大きいほど手前、小さい（マイナス含む）ほど奥に描画される
* まとめて描画順を制御したい場合には `CanvasLayer` を使用する
  * `CanvasLayer` の `Layer` の値が大きいほど手前、小さいほど奥に描画される