【Unity】全てのシーンのフォントを一括で置き換える

2015-06-13

UnityのNGUIを使ってるプロジェクトで使用するフォントを変更したいことがあったのだが、全てのシーンを開いて手作業で変更していくのは辛いのでスクリプトを書いた。

今回はNGUIのUILabelを使ったものに対して行ったが、uGUIのTextに対しても同様にできることでしょう。

メニューにウィンドウを開く項目を追加

// Assets/Editor/FontReplacer.cs
using UnityEngine;
using UnityEditor;

public class FontReplacer : EditorWindow {
[MenuItem("Tools/Replace Font")]
public static void ReplaceFont() {
EditorWindow.GetWindow(typeof(FontReplacer)).Show();
}
  • MenuItemという属性でUnityのメニューに項目を追加できる
  • EditWidnow を継承したクラスで、独自のウィンドウを作成できる

ウィンドウにフォントを選択する項目と置き換え開始ボタンを配置

// Assets/Editor/FontReplacer.cs
private Font font;
void OnGUI() {
font = EditorGUILayout.ObjectField("Font", font, typeof(Font), true) as Font;
if (font != null) {
if (GUILayout.Button("Replace font in all scenes")) {
string title = "Replacing [" + font.name + "]";
EachScene(title, (string path) => {
return ReplaceLabelsFontInScene(font);
});
}
}
}
  • OnGUIメソッド中でGUILayoutなどでボタンなどを配置する

シーン中のUILabelのfontを置き換える

// Assets/Editor/FontReplacer.cs
private static bool ReplaceLabelsFontInScene(Font font) {
UILabel[] labels = Object.FindObjectsOfType(typeof(UILabel)) as UILabel[];
if (labels.Length == 0)
return false;
foreach (UILabel label in labels)
label.trueTypeFont = font;
return true;
}
  • 実質の本体

全てのシーンを順に開いてなにかするメソッド

delegate bool OnScene(string path);
private static void EachScene(string title, OnScene onScene) {
string currentScene = EditorApplication.currentScene;
string[] sceneGuids = AssetDatabase.FindAssets("t:Scene");
for (int i = 0; i < sceneGuids.Length; ++i) {
string guid = sceneGuids[i];
string path = AssetDatabase.GUIDToAssetPath(guid);
EditorUtility.DisplayProgressBar(title, path, (float)i / (float)sceneGuids.Length);
EditorApplication.OpenScene(path);
if (onScene(path))
EditorApplication.SaveScene();
}
EditorUtility.ClearProgressBar();
if (!string.IsNullOrEmpty(currentScene))
EditorApplication.OpenScene(currentScene);
}
  • 処理中はプログレスバーを表示
  • onSceneからtrueが返された場合、シーンに更新があったものとして保存する
  • AssetDatabase.FindAssetsでシーンを列挙

  • シーンに存在する UILabel のフォントを置き換えるが、プレハブ化してあるものはノータッチなので、別途処理する必要がある