ぐーるらいふ

底辺。

【Unity】 文字列に含まれる絵文字を判別する

お世話になっております。ぐーるです。
また久しぶりになってしまいました。

ずっと開発はしてて、RPGとカードゲームを2本同時に作成しているのですが、
このRPG作るのが凄く楽しいのです。

シナリオ、システム、グラフィック、キャラクター
全部自分で用意するのですが、
キャラクターの絵を描く、描いたキャラクターをいきいきと会話させる、
といった事だけでとても楽しい。

「こんな会話させよう」「こうしたらこう展開出来るな」
といったシーンを考えて実装してるだけで楽しいです。
(現在進捗率70%)

妄想癖が功を奏するなんて事もあるのだな、と思います。

閑話休題、今日はunityで絵文字の判別をする方法を共有しようかなと。

unityで絵文字って使えるの?

基本的に使えません。
使おうと思うと特別なライブラリや対応を入れる必要があります。

baba-s.hatenablog.com

じゃあ対応する必要なくない?

使いたい、という要望があったり
外部サービスと連携していたりすると
対応する必要が出てきます。

判別方法

  1. 文字列からUnicode配列に変換
  2. Unicode配列からUTF32に変換
  3. UTF32で絵文字判定を行う

という手順で判別が可能です。
(コードは後ほど。先に絵文字とはというお話を)

Unicodeの絵文字って

www.unicode.org

Unicodeでは絵文字は上記ルールに沿って実現されています。
Unicode一つで表示出来るものもあれば、複数にまたがって表示しているものもあります。
これを一つ一つ判別する必要があります。

判別する方法として

の2つがあります。

正規表現パターンの方がオススメですが、
絵文字以外の文字を含めてしまう恐れがあります。
完全一致であれば、含めてしまう恐れが少なくなりますが、
追加があった場合、逐一入力する必要があります。

正規表現
iOSで扱われるUnicode 6.0絵文字の判定をする正規表現 · GitHub


完全一致例
Unity-UI-emoji/info.txt at master · mcraiha/Unity-UI-emoji · GitHub

実装

完全一致で実装する場合のコード例を共有します。
文字コードをまるっとソースに入れちゃってますが、
これはブログ用の実装で、プロジェクトにするならTextAssetsなど
の方が管理はしやすいでしょう。
また、絵文字コード表は全ては網羅出来ていないと思われますので、ご了承ください。

コード例)

    // inputからEmojiを取り除いた文を返却する
    public static string RemoveEmojiString(string inputString)
    {
        int i = 0;
        string firstString = null;
        string secondString = null;
        string threeString = null;
        string fourString = null;
        StringBuilder sb = new StringBuilder();
        var uint32Size = sizeof(UInt32);

        // unicode byte配列に文字列を変換
        byte[] unicodeBytes = Encoding.Unicode.GetBytes(inputString);

        // unicode配列からUTF32配列に変換
        var utf32Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF32, unicodeBytes);
        // 配列の長さ
        int length = utf32Bytes.Length / uint32Size;

        while (i < length)
        {
            // 1文字目をチェック
            firstString = BitConverter.ToUInt32(utf32Bytes, i * uint32Size).ToString("X4");

            // 2文字目までつなげてチェック
            if (i < (length - 1))
            {
                secondString = firstString + "-" + BitConverter.ToUInt32(utf32Bytes, (i + 1) * uint32Size).ToString("X4");
            }

            // 4文字目までつなげてチェック
            if (i < (length - 3))
            {
                threeString = BitConverter.ToUInt32(utf32Bytes, (i + 2) * uint32Size).ToString("X4");
                fourString = secondString + "-" + threeString + "-" + BitConverter.ToUInt32(utf32Bytes, (i + 3) * uint32Size).ToString("X4");
            }

            // 後ろから文字コード表と合わせてチェックして一致してたら絵文字と判断して読み飛ばす
            if (EMOJI_CODES.Any(e => e.Equals(fourString)))
            {
                i += 4;
            }
            else if (EMOJI_CODES.Any(e => e.Equals(secondString)))
            {
                i += 2;
            }
            else if (EMOJI_CODES.Any(e => e.Equals(firstString)))
            {
                i += 1;
            }
            else
            {
                // 正しい文字だけ投入
                sb.Append(Char.ConvertFromUtf32(BitConverter.ToInt32(utf32Bytes, i * uint32Size)));
                i += 1;
            }
        }

        return sb.ToString();
    }

    // 絵文字コード一覧表
    public static readonly string[] EMOJI_CODES =
    {
        "1F004",
        // 略 ~~~~~~~~
     };

文字コード一覧表をそのまま載せるとあまりにソースが長くなるので別ファイルにしました。

Unicode Emoji Code List · GitHub

あとがき

以上で絵文字の判別が出来ます。
コード見ると「はいはい、まあそうだよね」って感じですよね。

軽く調べるとサロゲートペアだけ判別すればいいよ、なんて
乱暴なコードもあったりして、ちょっと気になるなと思った次第です。

次はUnity1Weekの記事になりそうです。
うーん、もうちょっと更新したい。