Skip to content

Instantly share code, notes, and snippets.

@monry
Last active December 11, 2022 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save monry/8c20e41b144ff039956f8a44732169af to your computer and use it in GitHub Desktop.
Save monry/8c20e41b144ff039956f8a44732169af to your computer and use it in GitHub Desktop.
Unity 2022.1 で Localization 1.4.2 を使っているプロジェクトを iOS ビルドした際に PostprocessBuild で AmbiguousMatchException が発生して、アプリ名とかのローカライズが行われない問題に対するワークアラウンド
// VersionDefines を用いて「Localization v1.4.2 を用いていたら」的な Precompile Macro や、「Unity 2022.1.16f1 以上なら」みたいな条件を設定しても良いかも。
#if UNITY_EDITOR_OSX && UNITY_IOS
using System.Diagnostics;
using System.IO;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine.Localization.Settings;
using PackageInfo = UnityEditor.PackageManager.PackageInfo;
namespace Monry.Editor.Workaround
{
[InitializeOnLoad]
public class FixLocalization
{
private const string ChFlagsCommand = "/usr/bin/chflags";
private const string LockFlagName = "uchg";
private const string ReplacementSource = "s_PBXBuildFileDat.GetMethod(\"CreateFromFile\", BindingFlags.Static | BindingFlags.Public)";
private const string ReplacementDestination = "s_PBXBuildFileDat.GetMethod(\"CreateFromFile\", new Type[] { typeof(string), typeof(bool), typeof(string)})";
private const string EditorPrefsKey = "HasLocalizationWorkaroundRun";
private readonly string _scriptFilePath;
static FixLocalization()
{
EditorApplication.quitting -= UnlockPBXProjectExtensions;
EditorApplication.quitting += UnlockPBXProjectExtensions;
FixAndLockPBXProjectExtensions();
}
private FixLocalization(string scriptFilePath)
{
_scriptFilePath = scriptFilePath;
}
private static void FixAndLockPBXProjectExtensions()
{
if (EditorPrefs.GetBool(EditorPrefsKey))
{
return;
}
EditorPrefs.SetBool(EditorPrefsKey, true);
var scriptFilePath = ResolveScriptFilePath();
if (!File.Exists(scriptFilePath))
{
return;
}
new FixLocalization(scriptFilePath).Run();
}
private static void UnlockPBXProjectExtensions()
{
EditorPrefs.DeleteKey(EditorPrefsKey);
var scriptFilePath = ResolveScriptFilePath();
if (!File.Exists(scriptFilePath))
{
return;
}
new FixLocalization(scriptFilePath).LockFile(false);
}
private static string ResolveScriptFilePath()
{
var packageInfo = PackageInfo.FindForAssembly(typeof(LocalizationSettings).Assembly);
return $"Library/PackageCache/{packageInfo.packageId}/Editor/Platform/iOS/PBXProjectExtensions.cs";
}
private void Run()
{
LockFile(false);
ReplaceCode();
LockFile(true);
CompilationPipeline.RequestScriptCompilation();
}
private void ReplaceCode()
{
var script = File.ReadAllText(_scriptFilePath);
script = script.Replace(ReplacementSource, ReplacementDestination);
File.WriteAllText(_scriptFilePath, script);
}
private void LockFile(bool lockFlag)
{
var process = new Process();
process.StartInfo = new ProcessStartInfo(
ChFlagsCommand,
$"{(lockFlag ? string.Empty : "no")}{LockFlagName} '{_scriptFilePath}'"
);
process.Start();
process.WaitForExit();
}
}
}
#endif
@monry
Copy link
Author

monry commented Dec 6, 2022

ちょっとした解説

[InitializeOnLoad]

BuildPipeline.BuildPlayer() の前後で置換・ロック・アンロックを実行しても Localization のアセンブリがうまいことリロードされなかったため、[InitializeOnLoad] で実行している。

EditorApplication.quitting でのアンロック

ビルドサーバなどでビルドしている場合、コードがロックされたままだと、プロジェクトの Clean (ディレクトリごと削除とか)に失敗するケースがありうるので、エディタが落とされる時にアンロックする。

EditorPrefs

置換・ロックに成功した際に EditorPrefs にフラグを立てて、フラグが立っている場合は何も処理させないことで、無限コンパイルが起きないようにする。
(スクリプトの置換が行われずとも、chflags によるファイル操作が行われた時点で差分ありと見なされて再コンパイル → [InitializeOnLoad] 実行が発生してしまう。)

謝辞

matatabi-ux さんこちらのブログ記事がとても参考になりました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment