Edited at

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

More than 1 year has passed since last update.


背景

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

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