fluentui-emojiの絵文字をUnityで読み込む
マイクロソフトが提供しているオープンソースの絵文字データのFluent Emojiを、UnityのTextMeshProで読み込むための手順をご紹介します。
大まかな流れは以下の通りです。
- Fluent EmojiをClone
- SVG画像をPNG画像に変換
- Pythonスクリプトを実行してアトラスを作成
- Full Emoji Support Apiの変換ツールで、TextMeshPro用のSpriteAssetを作成
- SpriteAssetを修正して、
TMP_Emoji Text UGUI
コンポーネントにアタッチ
1. fluentui-emojiをClone
以下のサイトから、絵文字データをCloneします。
2. SVGファイルをPNGに変換
fluentui-emojiには、3D、Flat、Color、High Contrastの4種類の絵文字データが入っています。3DはPNG画像なので、変換がほぼ必要ない[1]ですが、その他の絵文字データがSVG画像なので、PNG画像に変換が必要です。Photoshopや、AffinityPhotoなどのツールを用いて、一括変換してください[2]。
3. Pythonスクリプトを実行してアトラスを作成
以下のPythonスクリプトを、Cloneしたfluentui-emojiディレクトリに作成して、実行してください。Pythonの環境設定は割愛します。
# fluentui-emojiのデータから、TMP Full Emoji Support Api用のアトラスを作成するスクリプト
# デフォルトでは1アトラスあたり、256個の絵文字が入ります。
# 1つのアトラスに入りきらない場合は、複数のアトラスを生成します。
import os
import json
from PIL import Image, UnidentifiedImageError
# 定数
ASSET_PATH = './assets' # 絵文字アセットのパス
EMOJI_TYPE = '3D' # 絵文字のタイプ: 3D, Color, Flat, High Contrast
EMOJI_DIR = '3D' # アトラスの生成ディレクトリ名、アトラス画像の末尾にも適用される
ATLAS_IMAGE_SIZE = 4096 # アトラスの画像サイズ
EMOJI_IMAGE_SIZE = 256 # 絵文字の画像サイズ
# 絵文字ディレクトリ一覧を取得
emojiDirs = os.listdir(ASSET_PATH)
# 絵文字数
emojiCount = 0
# アトラスの列数=行数
atlasColumnCount = int(ATLAS_IMAGE_SIZE / EMOJI_IMAGE_SIZE)
print("AtlasColumnCount: " + str(atlasColumnCount))
# アトラスに入る最大絵文字数
maxEmojiCountPerAtlas = int(ATLAS_IMAGE_SIZE / EMOJI_IMAGE_SIZE) ** 2
print("MaxEmojiCountPerAtlas: " + str(maxEmojiCountPerAtlas))
# アトラスのJson配列。アトラスごとにjsonを生成する。
atlasJsons = []
print("---- Scan Metadata ----")
for emojiDirName in emojiDirs:
# 各絵文字の内部ディレクトリ一覧を取得
emojiDataDirs = os.listdir(os.path.join(ASSET_PATH, emojiDirName))
# メタデータのjsonを読み込む
metaDataPath = os.path.join(ASSET_PATH, emojiDirName, 'metadata.json')
metadataJson = {}
with open(metaDataPath, encoding='utf-8') as jsonFile:
metadataJson = json.load(jsonFile)
# アトラスのID。絵文字がどのアトラスに入るか決める。
atlasId = int(emojiCount / maxEmojiCountPerAtlas)
# アトラス用のJsonがなければ生成
if len(atlasJsons) < atlasId + 1:
atlasJsons.append([])
# Jsonにパラメータを追加
emojiJson = {}
emojiJson["name"] = metadataJson["cldr"]
# Full Emoji Support Apiではimage名からコードポイントを取得する。
emojiJson["image"] = str(metadataJson["unicode"]).replace(" ", "-")
emojiJson["sheet_x"] = int((emojiCount - atlasId * maxEmojiCountPerAtlas) % atlasColumnCount)
emojiJson["sheet_y"] = int((emojiCount - atlasId * maxEmojiCountPerAtlas) / atlasColumnCount)
# スキントーンの有無を調べる。スキントーン対応絵文字は未対応。
hasSkintones = False
if "unicodeSkintones" in metadataJson:
hasSkintones = True
# 画像ディレクトリパスを生成
imageDir = os.path.join(ASSET_PATH, emojiDirName, EMOJI_TYPE)
# 画像ディレクトリが存在しなければ、パスを修正。スキントーン絵文字の場合は、Defaultディレクトリに画像が入っている。
if not os.path.isdir(imageDir):
imageDir = os.path.join(ASSET_PATH, emojiDirName, 'Default', EMOJI_TYPE)
if not os.path.isdir(imageDir):
# 画像ディレクトリが存在しなければ、空のパスをJsonに設定。
emojiJson["imagePath"] = ""
else:
imagePath = ""
imageDirFiles = os.listdir(imageDir)
for f in imageDirFiles:
if f.endswith(".png"): # PNGのみサポートする。
imagePath = f
break
imagePath = os.path.join(imageDir, imagePath)
emojiJson["imagePath"] = imagePath
emojiCount += 1
# 絵文字のJsonをアトラスのJsonに追加
atlasJsons[atlasId].append(emojiJson)
print("EmojiCount: " + str(emojiCount))
# 出力ディレクトリを作成
outputDir = "output" + "/" + EMOJI_DIR
os.makedirs("output", exist_ok=True)
os.makedirs(outputDir, exist_ok=True)
atlasCount = int(emojiCount / maxEmojiCountPerAtlas) + 1
print("AtlasCount: " + str(atlasCount))
# アトラス画像リスト
atlasList = []
print("---- Generate Atlas ----")
for atlasId in range(atlasCount):
atlas = Image.new('RGBA', (ATLAS_IMAGE_SIZE, ATLAS_IMAGE_SIZE), (0, 0, 0, 0))
atlasList.append(atlas)
atlasJson = atlasJsons[atlasId]
# Json出力
with open(outputDir + "/atlas" + format(atlasId, '0>2') + "_" + EMOJI_DIR + ".json", "w") as f:
json.dump(atlasJson, f, indent=4)
# 絵文字の画像をアトラスに貼り付ける。
for emojiJson in atlasJson:
if not emojiJson["imagePath"] == "":
try:
image = Image.open(emojiJson["imagePath"]).convert('RGBA')
x = emojiJson["sheet_x"]
y = emojiJson["sheet_y"]
atlas.paste(image, (x * EMOJI_IMAGE_SIZE, y * EMOJI_IMAGE_SIZE))
except UnidentifiedImageError as e:
print(e)
print("---- Write Atlas ----")
# アトラス画像を出力
for atlasId in range(atlasCount):
atlas = atlasList[atlasId]
atlas.save(outputDir + "/atlas" + format(atlasId, '0>2') + "_" + EMOJI_DIR + ".png", format="png")
print("---- Finished ----")
成功すると、output/3D
ディレクトリに、以下のようなファイルが生成されます。
Full Emoji Support Apiの変換ツールで、TextMeshPro用のSpriteAssetを作成
4.Unityプロジェクトを新規作成して、Full Emoji Support Apiを導入します。
生成した、PNG画像とJsonをUnityプロジェクトに入れて、Jsonファイルの拡張子を.txt
に変更します。
PNG画像のMaxSizeがデフォルトだと2048になっているので、全て4096に変更します。
Window > TextMeshPro > Sprite Emoji Importer
から、Sprite Emoji Importerウィンドウを開き、以下の画像のように設定し、Create Sprite Asset
ボタンを押して、成功したら、Save Sprite Asset
ボタンを押して、アセットを保存します。
(Glyph Scaleの効果がよくわからなかったので、誰か教えてください…)
これをアトラスの枚数分繰り返します。これでスプライトアセットは完成ですが、便利に使うために、もう少し設定が必要です。
6. SpriteAssetを修正して、TMP_Emoji Text UGUIコンポーネントにアタッチ
最初に作成したスプライトアセット(atlas00_3D)のFallback Sprite Assets
に、その他のスプライトアセットを追加します。
これは、最初のスプライトアセットに絵文字が存在しない場合に、他のアセットを探しに行くための設定です。以上で設定は完了です。
TMP_Emoji Text UGUI
コンポーネントのExtra Settings
にある、Sprite Asset
に最初に作成したスプライトアセット(atlas00_3D)をアタッチすると絵文字を表示できるようになります[3]。
Pythonスクリプトを改造すると、他の種類の絵文字を出力したり、画像サイズの変更もできますので、ぜひお試しください!
Discussion