複数Live2Dモデルの描画順を制御する

複数のLive2Dモデルを表示する場合、描画順をZ値で上手く制御できなかったのでやり方をまとめてみました。
![01.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/67bb5f34-f3f7-d4b4-1410-6e3382611a0f.gif)

主にやり方は以下の2つありました。

# １．描画タイミングを管理するスクリプト作る
[Live2D コミュニティ](http://forum.live2d.com/)で以下のスレッドがあったので、SDKのMotionプロジェクトをカスタムして試してみました。
　→　[UnityでLive2dを使うときに描画順を制御するにはどうしたらいいでしょうか？](http://forum.live2d.com/discussion/165/unity%E3%81%A7live2d%E3%82%92%E4%BD%BF%E3%81%86%E3%81%A8%E3%81%8D%E3%81%AB%E6%8F%8F%E7%94%BB%E9%A0%86%E3%82%92%E5%88%B6%E5%BE%A1%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%E3%81%A9%E3%81%86%E3%81%97%E3%81%9F%E3%82%89%E3%81%84%E3%81%84%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%81%8B/p1)

１）まずは2体のLive2Dモデルを用意します(スクリプトは同じものをアタッチ)
![02.png](https://qiita-image-store.s3.amazonaws.com/0/15028/f04e4e94-3cb6-8281-694a-0a674dcced5f.png)

２）SimpleModel.csのOnrenderObject()を適当な名前に変えます

```Csharp:SimpleModel.cs
	//void OnRenderObject()
	public void RenderLive2D()
	{
        if (live2DModel == null) return;
        live2DModel.setMatrix(transform.localToWorldMatrix * live2DCanvasPos);
　　　　.
　　　　.
　　　　.
```

３）空のGameObjectを作り、スクリプトを作ります
![03.png](https://qiita-image-store.s3.amazonaws.com/0/15028/104c6d65-954c-ff6c-c9e1-ece4d9e03251.png)

```Csharp:RenderControl.cs
using UnityEngine;
using System.Collections;

public class RenderControl : MonoBehaviour {

	[Range(0,1)]
	public int changemodel;	// 前面に出すモデル切替

	private SimpleModel obj_haru;		// haruモデル
	private SimpleModel obj_Epsilon;	// Epsilonモデル

	void Start () {
		// スクリプトを取得する
		obj_haru = GameObject.Find("haru").GetComponent<SimpleModel>();
		obj_Epsilon = GameObject.Find("Epsilon").GetComponent<SimpleModel>();
	}

	void OnRenderObject(){
		if (changemodel == 0)
		{
			obj_haru.RenderLive2D();
			obj_Epsilon.RenderLive2D();
		}
		else
		{
			obj_Epsilon.RenderLive2D();
			obj_haru.RenderLive2D();
		}
	}
}
```
これで描画順を制御できます！
![04.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/92216f74-267a-974f-af16-e045ff830a83.gif)
*書き終わってから指摘を受けたけど、Live2DモデルのZ値でどっちを先に描画するか指定する方が賢いですね*

# ２．描画モードを変更しZ値で制御する
もう１つのやり方が描画モードをDRAW_MESH_NOWからDRAW_MESHに変更する方法です。
　→　[Live2D Manual - 描画モードの設定について](http://sites.cybernoids.jp/cubism2/sdk_tutorial/platform-setting/unity/csharp/render-mode)

こちらはスクリプトを以下のように描画モードとOnRenderObjectをUpdateに変更するだけです。

**2015/09/17追記**
**Live2D Unity SDK2.1からクリッピングマスク使用モデルの場合は[live2DModel.updateのタイミングが変更](http://sites.cybernoids.jp/cubism-sdk2/2-1-sdk-updated)**


```Csharp:SimpleModel.cs
using UnityEngine;
using System;
using System.IO;
using System.Collections;
using live2d;

[ExecuteInEditMode]
public class SimpleModel: MonoBehaviour 
{
    private Live2DModelUnity live2DModel;
    private Live2DMotion motion;
    private MotionQueueManager motionMgr;
    private Matrix4x4 live2DCanvasPos;
    public TextAsset mocFile ;
    public Texture2D[] textureFiles ;
    public TextAsset motionFile;

	void Start () 
	{
        Live2D.init();

        live2DModel = Live2DModelUnity.loadModel(mocFile.bytes);
		// Live2Dのレンダーモード変更
		live2DModel.setRenderMode(Live2D.L2D_RENDER_DRAW_MESH);

        for (int i = 0; i < textureFiles.Length; i++)
        {
            live2DModel.setTexture(i, textureFiles[i]);
        }

        float modelWidth = live2DModel.getCanvasWidth();
        live2DCanvasPos = Matrix4x4.Ortho(0, modelWidth, modelWidth, 0, -50.0f, 50.0f);

        motionMgr = new MotionQueueManager();
        motion = Live2DMotion.loadMotion(motionFile.bytes);
	}

	//void OnRenderObject()
	public void Update()
	{
        if (live2DModel == null) return;
        live2DModel.setMatrix(transform.localToWorldMatrix * live2DCanvasPos);

        if ( ! Application.isPlaying)
        {
            live2DModel.update();
            live2DModel.draw();
            return;
        }

        if (motionMgr.isFinished())
        {
            motionMgr.startMotion(motion);
        }

        motionMgr.updateParam(live2DModel);
		
		live2DModel.update();
		live2DModel.draw();
	}
}
```
こちらの方式ならZ値をいじるだけで描画順を制御できます
![05.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/ea825e7b-af3b-d473-60ff-a9085d898ee7.gif)

また、パーティクルなども描画順が制御できます。

ただ、[Live2Dの描画の裏側の話](http://www.slideshare.net/naokiaso75/live2-d?qid=b1a10ce1-41cd-473a-879a-bd180c291bf7&v=default&b=&from_search=1)のスライドにもあった通り、こちらは削除されるAPI方式です。
Unity5.0.1で確認しましたが、まだ使えるAPIっぽいのでやりやすい方で描画順を制御すればＯＫかと思います。

# ３．RenderTextureを使う
Live2D Unity SDKにはRenderTextureプロジェクトがあります。
こちらならRenderTextureを使ってPlaneにLive2Dモデルを表示するので、普通の3Dオブジェクトと同じように扱えます。
Unity5になってFree版でもRenderTextureが使えるようになったので、使うといいです。

ただし、通常よりもドローコール数が2倍になります。

参考　→　[Q. 半透明のマテリアルを設定したゲームオブジェクトが、Live2Dのモデルの前に表示できません。](http://sites.cybernoids.jp/cubism2/faq/develop/unity#Q07)