Unity から Export した iOS なアプリの Bundle Display Name を自動設定してみる

  • 29
    Like
  • 0
    Comment

背景

Unity から出力した iOS プロジェクトに、ローカライズしたアプリ名 (CFBundleDisplayName) を付与するのに苦労したので、その辺のお話しを書き殴る。

まぁ、元同僚から「ぼすけて!」って言われたので書いてるのは内緒w べ、別に貴方のためなんかじゃないんだからっ!

概要

大前提として PostProcessBuild で対応する。

流れとしては以下のような感じ。

  1. InfoPlist.strings に各言語でのアプリ名を書き込む
  2. <language>.lproj/ ディレクトリに格納
  3. Unity-iPhone.xcodeproj/project.pbxproj を弄る
    1. KnownRegion に言語を追加
    2. 生成した InfoPlist.strings を VariantGroup として束ねる

詳細

先ず、事前準備として、 XCodeEditor for Unity という .pbxproj ファイルを弄れるアセットを入れておく。

ただし、上記のリポジトリは最近メンテされてないっぽくて、素のままだと今回やりたい処理ができないので、ちょっと手を入れたモノを XCodeEditor for Unity (forked by monry) に置いておいたので、今回はコッチを使う。

InfoPlist.strings に書き込む

内容は

InfoPlist.strings
CFBundleDisplayName = "アプリ名";

ってな感じ。

この辺は頑張って C# ガリガリ書いてください。

<language>.lproj/ ディレクトリに格納

まぁ、この辺も普通に C# で書けば良いんじゃないかな。

出力先としては PostProcessBuild に渡される path + "<language>.lproj/InfoPlist.strings" とかで良いかと。

言語追加しつつ、VariantGroup として束ねる

この投稿のメインテーマ。

基本的には、PBXVariantGroup 型の変数にファイルの参照を突っ込んで、.pbxproj に書き込むってな流れ。

XCodeEditor for Unity の改修点としては以下の通り。

  • 言語の追加を行うヘルパメソッドを PBXProject クラスに追加した
  • PBXVariantGroup を PBXGroup のサブクラスとして定義し直した
    • XCodeEditor.XCProject.AddFile() の第2引数に PBXGroup のインスタンスを渡せば、その下に追加してくれるような実装になっているので、その処理をそのまま利用するため。

なので、その辺を利用して言語追加しつつ、生成した .strings ファイルをプロジェクトに食わせつつ VariantGroup の子要素として紐付ける感じ。

コード

色々端折ってるけど、上記を纏めると以下のようなコードになる。はず。

PostProcessBuild.cs
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.XCodeEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;

public static class PostProcessBuild {

    private static Dictionary<string, string> appNameMap = new Dictionary<string, string>() {
        { "en", "HogeHoge" },
        { "ja", "ほげほげ" },
    };

    [PostProcessBuild(100)]
    public static void OnPostProcessBuild(BuildTarget target, string path) {
        // 出力済のディレクトリを XCodeEditor に食わせる
        XCProject project = new XCProject(path);

        // VariantGroup 作成
        PBXVariantGroup infoPlist = project.GetVariantGroup("InfoPlist.strings");
        foreach (KeyValuePair<string, string> entry in appNameMap) {
            // 文字コードを変換しておく
            string appNameConverted = System.Text.Encoding.UTF8.GetString(
                System.Text.Encoding.Convert(
                    System.Text.Encoding.Unicode,
                    System.Text.Encoding.UTF8,
                    System.Text.Encoding.Unicode.GetBytes(entry.Value)
                )
            );

            // 格納用ディレクトリ作成
            if (!Directory.Exists(Path.Combine(path, string.Format("{0}.lproj", entry.Key)))) {
                Directory.CreateDirectory(Path.Combine(path, string.Format("{0}.lproj", entry.Key)));
            }

            // InfoPlist.strings 作成
            StreamWriter w = new StreamWriter(Path.Combine(path, string.Format("{0}.lproj/InfoPlist.strings", entry.Key)), false);
            w.WriteLine(string.Format("CFBundleDisplayName = \"{0}\";", appNameConverted));
            w.Close();

            // KnownRegion に言語を追加
            project.project.AddKnownRegion(entry.Key);

            // ファイルの参照を追加
            project.AddFile(Path.Combine(path, string.Format("{0}.lproj/InfoPlist.strings", entry.Key)), infoPlist, "SOURCE_ROOT", true, false, string.Format("{0}.lproj/InfoPlist.strings", entry.Key));
        }

        // 上書き保存
        project.Save();
    }

}

なお、BuildTarget による処理の振り分けとか一切やってないので悪しからずw

あと、これの処理を連続でキックすると、重複してファイルが追加されてしまうので、その辺は巧いコト回避してくださいな。