[Unity][Android][OculusQuest] 形態素解析MeCabを使ってみる

#１．はじめに
OculusQuest(Android)で形態素解析を行ってみたかったので、その調査結果を載せておきます。
ちなみに自分の[Blog](https://www.xr-develop.com/2019/09/unityandroidoculusquest-mecab.html)でも同様の記事を作成しています。

#２．検証した環境
・Unity 2018.4.1f1
・Oculus Quest

#３．手順
(1) NMecabをダウンロードする
　NMeCabは、MeCabのエンジン処理を.NETで書き直してくれてたオープンソースです。
　Windows用にDLLが格納されていますが、今回はソースを使います。
　最新バージョンはNMecab0.07となります。（2019/9/25現在)
　https://ja.osdn.net/projects/nmecab/

 (2)プロジェクト設定を行う
　NMeCabのソースを使う為に以下の設定を行います。
　①.NET4 を使用するように設定する
　② Allow unsafe Code にチェックする
![Image 2019-09-25 16.13.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210301/eb472691-0902-859b-4c46-db437cc2aad9.png)
　
 (3)ソースと辞書ファイルを配置する
　① UnityのAssetsフォルダに以下のフォルダを作成します。
　　・ Assets/NMecab
　　・ Assets/StreamingAssets/NMecab

　②１．でダウンロードした圧縮ファイルの中にあるファイルを格納していきます。
　　・NMeCab0.07\src\LibNMeCab を Assets/NMecab 下にコピーします。
 ![D__unity_VRDevelop1_NMeCab0.07_src 2019-09-25 16.26.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210301/121a7fdf-e80e-a149-e4f7-b061ad95476e.png)
　　・NMeCab0.07\dic\ipadicの直下にあるすべての辞書ファイルを Assets/StreamingAssets/NMecab下にコピーします。
![Unity 2018.4.1f1 Personal - [PREVIEW PACKAGES IN USE] - Web.unity - VRDevelop1 - Android _DX11 on DX9 GPU_ 2019-09-25 16.32.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210301/6b4e93f6-cb26-1567-f22b-8c224bf037bb.png)

　(4)プログラムから呼び出す
　Androidの場合、StreamingAssetsに配置したファイルを読み込み場合、WWWを使って読み込む必要があります。そうなるとNMeCabのソースを変更しないといけなくなるので辞書ファイルは一旦OculusQuest(Android)端末へコピーしてからそのファイルを読み込むようにします。

　以下のスクリプトからのオブジェクトに張り付けて実行してみましょう。

```C#:MecabTest.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using NMeCab;
using System.IO;

public class MecabTest : MonoBehaviour
{

	void Update()
	{
	}

	void Start ()
	{
	    //端末へMecabの辞書ファイルをコピー
	    CopyFile(Application.streamingAssetsPath + "/NMeCab", Application.persistentDataPath, "char.bin");
	    CopyFile(Application.streamingAssetsPath + "/NMeCab", Application.persistentDataPath, "dicrc");
	    CopyFile(Application.streamingAssetsPath + "/NMeCab", Application.persistentDataPath, "matrix.bin");
	    CopyFile(Application.streamingAssetsPath + "/NMeCab", Application.persistentDataPath, "unk.dic");
	    CopyFile(Application.streamingAssetsPath + "/NMeCab", Application.persistentDataPath, "sys.dic");

	    //Mecabの読み込み
	    param = new MeCabParam();
	    param.DicDir = Application.persistentDataPath;

	    //テスト
	    SetKeyWord("今日はとても良い天気ですね。");
	}

	/// 
	/// copy dictionary file.
	/// 
	/// void
	/// from path
	/// to path
	/// copy file name
	void CopyFile(string from, string to, string fileName) {
	    string path = from + "/" + fileName;
	    string toPath = to + "/" + fileName;

	#if UNITY_EDITOR || UNITY_IPHONE
	    FileInfo file = new FileInfo(path);
	    file.CopyTo(toPath, true);

	#elif UNITY_ANDROID
	    WWW www = new WWW (path);
	    while (!www.isDone) {
		}

	    File.WriteAllBytes (toPath, www.bytes);
	#endif
	}


	/// 
	/// Shows the key word.
	/// 
	/// The key word.
	/// Sentence.
	public void SetKeyWord(string sentence) {
	    MeCabTagger tagger = MeCabTagger.Create(param);
	    MeCabNode node = tagger.ParseToNode(sentence);

	    while (node != null)
	    {
	        if (node.CharType > 0)
	        {
				//名詞のみ抽出
	            if (node.Feature.IndexOf ("名詞") >= 0) {
	                Debug.Log ("名詞：" + node.Surface);
	            }
	        }
	        node = node.Next;
	    }
	}
}
```

Windows環境であれば辞書ファイルのコピーは不要なので、あくまでAndroid向けの処理となっています。
その辺は各自工夫してもらえれば良いかなと思います。