Unityで日本語の形態素解析を行うために、
軽量・簡単に使える NMeCab を導入してみました!
この記事では、
- NMeCabの導入方法
- Unityへの組み込み手順
- メソッド別の解析サンプル
をまとめています!
🚀 NMeCab導入手順
1. DLLファイルをダウンロード
まず、NMeCabのリリースページからDLLファイルを取得します。
ダウンロードするファイル:
- NMeCab.dll
2. Unityプロジェクトに配置
- Unityプロジェクト内に
Assets/Plugins/フォルダを作成 NMeCab.dllをAssets/Plugins/に配置します。
3. 辞書データ(ipadicなど)を用意
NMeCabのReleaseページにある「Source code.zip」をダウンロードしてください。
その中にある dic/ipadic/ フォルダ内のファイルを、
Unityプロジェクト内の Assets/StreamingAssets/NMeCab/ フォルダを作成し、移動します。

⚙️ Unityセットアップ用コード
💬 注意
Unityでは通常StreamingAssetsに辞書ファイルを置きますが、
Androidの場合は直接アクセスできない場合があったため、最初にpersistentDataPathへコピーして使用します。
using System; using System.Collections; using System.IO; using System.Text; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Networking; using NMeCab.Specialized; public class MeCabWrapper { private MeCabIpaDicTagger _tagger; public MeCabIpaDicTagger Tagger => _tagger; public async Task SetUp() { await SetUp(Path.Combine(Application.streamingAssetsPath, "NMeCab")); } public async Task SetUp(string path) { #if UNITY_ANDROID && !UNITY_EDITOR await CopyFile(path, Application.persistentDataPath, "char.bin"); await CopyFile(path, Application.persistentDataPath, "matrix.bin"); await CopyFile(path, Application.persistentDataPath, "sys.dic"); await CopyFile(path, Application.persistentDataPath, "unk.dic"); await CopyFile(path, Application.persistentDataPath, "dicrc"); path = Application.persistentDataPath; #endif await Task.Yield(); _tagger = MeCabIpaDicTagger.Create(path); } #if UNITY_ANDROID && !UNITY_EDITOR private async Task CopyFile(string from, string to, string fileName) { var path = Path.Combine(from, fileName); var toPath = Path.Combine(to, fileName); using (var www = UnityWebRequest.Get(path)) { var request = www.SendWebRequest(); while (!request.isDone) await Task.Yield(); if (www.result == UnityWebRequest.Result.Success) { var data = www.downloadHandler.data; await File.WriteAllBytesAsync(toPath, data); } else { Debug.LogError(www.error); } } } #endif }
メソッド別サンプルとログ
🔹 Parse
標準的な形態素解析。単語を分割し、品詞情報を付与します。
サンプルコード
var text = "すもももももももものうち"; var parse = wrapper.Tagger.Parse(text); foreach (var node in parse) { Debug.Log(node.ToString()); }
実行ログ
[Surface:すもも][Feature:名詞,一般,*,*,*,*,すもも,スモモ,スモモ][BPos:0][EPos:3][RCAttr:1285][LCAttr:1285][PosId:38][CharType:6][Stat:0][IsBest:True][Alpha:0][Beta:0][Prob:0][Cost:7263] [Surface:も][Feature:助詞,係助詞,*,*,*,*,も,モ,モ][BPos:3][EPos:4][RCAttr:262][LCAttr:262][PosId:16][CharType:6][Stat:0][IsBest:True][Alpha:0][Beta:0][Prob:0][Cost:7774] [Surface:もも][Feature:名詞,一般,*,*,*,*,もも,モモ,モモ][BPos:4][EPos:6][RCAttr:1285][LCAttr:1285][PosId:38][CharType:6][Stat:0][IsBest:True][Alpha:0][Beta:0][Prob:0][Cost:15010] ...
🔹 ParseNBest
曖昧な単語解析時に、複数パターンを取得できるメソッドです。
サンプルコード
var parseNBest = wrapper.Tagger.ParseNBest("もも"); foreach (var result in parseNBest) { foreach (var node in result) { Debug.Log(node.ToString()); } }
実行ログ
[Surface:もも][Feature:名詞,一般,*,*,*,*,もも,モモ,モモ][BPos:0][EPos:2][RCAttr:1285][LCAttr:1285][PosId:38][CharType:6][Stat:0][IsBest:True][Alpha:0][Beta:0][Prob:0][Cost:6936] [Surface:もも][Feature:動詞,自立,*,*,五段・マ行,未然ウ接続,もむ,モモ,モモ][BPos:0][EPos:2][RCAttr:763][LCAttr:763][PosId:31][CharType:6][Stat:0][IsBest:False][Alpha:0][Beta:0][Prob:0][Cost:9917] [Surface:も][Feature:助詞,係助詞,*,*,*,*,も,モ,モ][BPos:0][EPos:1][RCAttr:262][LCAttr:262][PosId:16][CharType:6][Stat:0][IsBest:False][Alpha:0][Beta:0][Prob:0][Cost:6198] ...
🔹 ParseSoftWakachi
単語単位でやさしく(ソフトに)分かち書きするメソッドです。
サンプルコード
var parseSoftWakachi = wrapper.Tagger.ParseSoftWakachi("もも"); foreach (var node in parseSoftWakachi) { Debug.Log(node.ToString()); }
実行ログ
[Surface:もも][Feature:動詞,自立,*,*,五段・マ行,未然ウ接続,もむ,モモ,モモ][BPos:0][EPos:2][RCAttr:763][LCAttr:763][PosId:31][CharType:6][Stat:0][IsBest:False][Alpha:-7437.75][Beta:-576][Prob:0][Cost:9917] [Surface:もも][Feature:名詞,一般,*,*,*,*,もも,モモ,モモ][BPos:0][EPos:2][RCAttr:1285][LCAttr:1285][PosId:38][CharType:6][Stat:0][IsBest:True][Alpha:-5202][Beta:429.75][Prob:1][Cost:6936] ...
🔹 ParseToLattice
解析結果をラティス構造(格子)で取得。詳細なスコア情報にもアクセスできます。
サンプルコード
var lattice = wrapper.Tagger.ParseToLattice("もも", new MeCabParam()); Debug.Log(lattice.BosNode.ToString()); Debug.Log(lattice.EosNode.ToString()); foreach (var node in lattice.BeginNodeList) { Debug.Log(node.ToString()); } foreach (var node in lattice.EndNodeList) { Debug.Log(node.ToString()); }
実行ログ
[Surface:BOS][Feature:][BPos:0][EPos:0][RCAttr:0][LCAttr:0][PosId:0][CharType:0][Stat:2][IsBest:True][Alpha:0][Beta:0][Prob:0][Cost:0] [Surface:EOS][Feature:][BPos:2][EPos:2][RCAttr:0][LCAttr:0][PosId:0][CharType:0][Stat:3][IsBest:True][Alpha:0][Beta:0][Prob:0][Cost:6363] [Surface:もも][Feature:動詞,自立,*,*,五段・マ行,未然ウ接続,もむ,モモ,モモ][BPos:0][EPos:2][RCAttr:763][LCAttr:763][PosId:31][CharType:6][Stat:0][IsBest:False][Alpha:0][Beta:0][Prob:0][Cost:9917] [Surface:も][Feature:動詞,自立,*,*,五段・ラ行,体言接続特殊2,もる,モ,モ][BPos:1][EPos:2][RCAttr:776][LCAttr:776][PosId:31][CharType:6][Stat:0][IsBest:False][Alpha:0][Beta:0][Prob:0][Cost:16926] ...