以下の内容はhttps://hacchi-man.hatenablog.com/entry/2025/04/20/220000より取得しました。


【Unity】NMeCabを導入して使ってみた

Unityで日本語の形態素解析を行うために、
軽量・簡単に使える NMeCab を導入してみました!

この記事では、

  • NMeCabの導入方法
  • Unityへの組み込み手順
  • メソッド別の解析サンプル

をまとめています!

🚀 NMeCab導入手順

1. DLLファイルをダウンロード

まず、NMeCabのリリースページからDLLファイルを取得します。

NMeCab Releaseページ

ダウンロードするファイル: - NMeCab.dll

2. Unityプロジェクトに配置

  • Unityプロジェクト内に Assets/Plugins/ フォルダを作成
  • NMeCab.dllAssets/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]
...



以上の内容はhttps://hacchi-man.hatenablog.com/entry/2025/04/20/220000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14