using System.IO; using System.Linq; using System.Text.RegularExpressions; using UnityEditor; using UnityEditor.Build.Reporting; using UnityEngine; namespace Luneraria.EditorTools { /// /// Player builds (U2D). Only macOS is possible on this machine; Windows and Linux need the build /// modules listed in docs/port/U1.5-UNITY.md. Output goes to Builds/ (ignored by git). /// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LunePlayerBuild.BuildMac -logFile - /// public static class LunePlayerBuild { static string Root { get { return Path.GetDirectoryName(Application.dataPath); } } public static void BuildMac() { string path = Path.Combine(Root, "Builds/macOS/Luneraria.app"); foreach (string copy in ConflictCopies()) { Debug.Log("LUNE_BUILD removing conflict copy " + copy); File.Delete(copy); } // CPU and GPU frame timings for the benchmark (FrameTimingManager). PlayerSettings.enableFrameTimingStats = true; var options = new BuildPlayerOptions { scenes = new[] { LuneWorldBuilder.ScenePath }, locationPathName = path, target = BuildTarget.StandaloneOSX, options = BuildOptions.None, }; BuildReport report = BuildPipeline.BuildPlayer(options); Debug.Log(string.Format("LUNE_BUILD {0}: {1}, {2:0.0} MB, {3:0.0} s", report.summary.result, path, report.summary.totalSize / 1048576.0, report.summary.totalTime.TotalSeconds)); foreach (PackedAssets packed in report.packedAssets) { ulong total = 0; foreach (PackedAssetInfo info in packed.contents) total += info.packedSize; Debug.Log(string.Format("LUNE_BUILD file {0}: {1} objects, {2:0.0} MB", packed.shortPath, packed.contents.Length, total / 1048576.0)); foreach (PackedAssetInfo info in packed.contents.OrderByDescending(c => c.packedSize).Take(5)) Debug.Log(string.Format("LUNE_BUILD {0:0.00} MB {1} {2}", info.packedSize / 1048576.0, info.type, info.sourceAssetPath)); Directory.CreateDirectory(Path.Combine(Root, "tools/out")); File.WriteAllLines(Path.Combine(Root, "tools/out/build-" + packed.shortPath + ".txt"), packed.contents.Select(c => c.packedSize + " " + c.type + " " + c.sourceAssetPath)); } string[] appeared = ConflictCopies(); foreach (string copy in appeared) Debug.LogError("LUNE_BUILD conflict copy appeared during the build: " + copy); bool trusted = appeared.Length == 0; if (!trusted) Debug.LogError("LUNE_BUILD the build may carry stale script layouts; build again"); EditorApplication.Exit(report.summary.result == BuildResult.Succeeded && trusted ? 0 : 1); } /// /// Copies a sync service (iCloud Drive) keeps of a replaced file, named "name 2.ext". In the /// build cache a copy of an old player assembly enters the build's type database before the /// current one, scripted objects are then written with the old field layout and the player /// reports sharedassets0.assets as corrupted. Only build caches are searched; a copy is one /// whose original (without " 2") exists next to it. /// static string[] ConflictCopies() { var copy = new Regex(@"^(.+) \d+(\.[^.]+)?$"); return new[] { "Library/Bee", "Library/BuildPlayerData", "Library/PlayerDataCache" } .Select(folder => Path.Combine(Root, folder)) .Where(Directory.Exists) .SelectMany(folder => Directory.GetFiles(folder, "* *", SearchOption.AllDirectories)) .Where(file => { Match match = copy.Match(Path.GetFileName(file)); return match.Success && File.Exists(Path.Combine(Path.GetDirectoryName(file), match.Groups[1].Value + match.Groups[2].Value)); }) .OrderBy(file => file, System.StringComparer.Ordinal) .ToArray(); } } }