ProjectDDD/Assets/_Datas/SLShared/SLUnity/Editor/SLBuild/SLAppBuild.cs
2025-06-17 20:47:57 +09:00

345 lines
11 KiB (Stored with Git LFS)
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using Superlazy;
using Superlazy.Loader;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.Callbacks;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
#if UNITY_IOS
using UnityEditor.iOS.Xcode;
#endif
public class SLAppBuild
{
public static string dataAssetPath = "Addressables/Data";
private static readonly SLEntity options = SLEntity.Empty;
private enum SLAppBuildTarget
{
NONE = -1,
iOS = 0,
Android = 4,
Android_x86 = 5,
iOS_Cheat = 8,
Android_Cheat = 9
}
private static void ParseCommandLine()
{
var args = Environment.GetCommandLineArgs();
for (var i = 0; i < args.Length; ++i)
{
if (args[i].IsLeft("-"))
{
if (args[i + 1].Contains(","))
{
var splits = args[i + 1].Split(',');
for (var j = 0; j < splits.Count(); ++j)
{
options[args[i].Replace("-", "")][j.ToString()] = splits[j];
}
++i;
}
else
{
options[args[i].Replace("-", "")] = args[i + 1];
++i;
}
}
}
}
public static void BuildAndroidAPK()
{
PreBuild();
PlayerSettings.Android.bundleVersionCode = options["BuildSettings"]["BuildVersion"];
PlayerSettings.Android.keystorePass = options["BuildSettings"]["Android"]["KeystorePass"];
PlayerSettings.Android.keyaliasName = options["BuildSettings"]["Android"]["KeyaliasName"];
PlayerSettings.Android.keyaliasPass = options["BuildSettings"]["Android"]["KeyaliasPass"];
EditorUserBuildSettings.buildAppBundle = false;
var outputName = Application.productName + ".apk";
GenericBuild(outputName, BuildTargetGroup.Android, BuildTarget.Android, BuildOptions.None);
}
public static void BuildiOSIPA()
{
PreBuild();
var targetDir = "./build";
PlayerSettings.iOS.buildNumber = options["BuildSettings"]["BuildVersion"];
var opt = BuildOptions.None;
PlayerSettings.statusBarHidden = true;
if (Directory.Exists(targetDir))
{
Directory.Delete(targetDir, true);
}
if (Directory.Exists(targetDir) == false)
{
Directory.CreateDirectory(targetDir);
}
GenericBuild(targetDir, BuildTargetGroup.iOS, BuildTarget.iOS, opt);
}
public static void PreBuild()
{
LoadBuildSettings();
ParseCommandLine();
UpdateDataScript();
UpdateAddressable();
UpdateLoaderID();
}
private static void GenericBuild(string target_path, BuildTargetGroup buildTargetGroup, BuildTarget build_target, BuildOptions build_options)
{
var levels = GetLevelsFromBuildSettings();
EditorUserBuildSettings.SwitchActiveBuildTarget(buildTargetGroup, build_target);
// TODO: NamedBuildTarget으로 개선
if (options["Def"])
{
// 기존 심볼들
var existingDefs = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup)
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(d => d.Trim())
.ToHashSet();
// 새로 추가할 심볼들
var newDefs = options["Def"].ToString()
.Split(";", StringSplitOptions.RemoveEmptyEntries)
.Select(d => d.Trim());
// 병합 후 중복 제거
foreach (var def in newDefs)
existingDefs.Add(def);
// 최종 적용
var mergedDefs = string.Join(";", existingDefs);
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, mergedDefs);
}
var res = BuildPipeline.BuildPlayer(levels, target_path, build_target, build_options);
if (res.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
{
throw new Exception("BuildPlayer failure: " + res.summary.ToString());
}
}
private static string[] GetLevelsFromBuildSettings()
{
var levels = new List<string>();
foreach (var scene in EditorBuildSettings.scenes)
{
levels.Add(scene.path);
}
return levels.ToArray();
}
public static void LoadBuildSettings()
{
var path = Path.Combine(Application.dataPath, "SLBuild", "BuildSettings.json");
options["BuildSettings"] = JsonLoader.LoadJson(File.ReadAllText(path))["BuildSettings"];
}
public static void UpdateDataScript()
{
FileUtil.DeleteFileOrDirectory("Assets/Addressables/Data/");
var destDir = Path.Combine(Application.dataPath, dataAssetPath);
Directory.CreateDirectory(destDir);
var loader = SLSystemUtility.CreateInstance<SLDataLoader>("SLWindowsLoader");
var system = SLSystemUtility.CreateInstance<SLSystem>("SLSystem");
system.Init(loader, DateTime.UtcNow);
loader.Load();
foreach (var session in SLSystem.Data)
{
var fileName = session.ID + ".json";
var paths = Path.Combine(destDir, fileName).Split(Path.DirectorySeparatorChar);
var path = "";
for (var i = 0; i < paths.Length - 1; ++i)
{
path += paths[i] + Path.DirectorySeparatorChar;
if (Directory.Exists(path) == false)
{
Directory.CreateDirectory(path);
}
}
var saveData = SLEntity.Empty;
saveData[session.ID] = session;
var text = JsonLoader.SaveToJson(saveData);
SLFileUtility.MakeFolderFromFilePath(Path.Combine(destDir, fileName));
File.WriteAllText(Path.Combine(destDir, fileName), text, Encoding.UTF8);
}
AssetDatabase.Refresh();
}
private static void UpdateAddressable()
{
AssetDatabase.ImportAsset("Assets/Addressables", ImportAssetOptions.ImportRecursive);
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
var settings
= AddressableAssetSettingsDefaultObject.Settings;
settings.activeProfileId
= settings.profileSettings.GetProfileId("Default");
var builder
= AssetDatabase.LoadAssetAtPath<ScriptableObject>("Assets/AddressableAssetsData/DataBuilders/BuildScriptPackedMode.asset") as IDataBuilder;
settings.ActivePlayerDataBuilderIndex
= settings.DataBuilders.IndexOf((ScriptableObject)builder);
AddressableAssetSettings.BuildPlayerContent(out var result);
if (!string.IsNullOrEmpty(result.Error))
throw new Exception(result.Error);
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
}
public static void UpdateLoaderID()
{
EditorSceneManager.OpenScene("Assets/Scenes/Game.unity");
var slunity = UnityEngine.Object.FindFirstObjectByType<SLUnity>();
if (slunity != null)
{
slunity.loaderID = "SLUnityDataLoader";
}
EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
}
[PostProcessBuild(999)]
public static void OnPostProcessBuild(BuildTarget buildTarget, string path)
{
if (buildTarget == BuildTarget.StandaloneWindows64)
{
var folderPath = SLFileUtility.FolderPath(path);
var backupFolder = folderPath + "/" + Application.productName + "_BackUpThisFolder_ButDontShipItWithYourGame";
if (Directory.Exists(backupFolder))
{
Directory.Delete(backupFolder, true);
}
var burstDebugFolder = folderPath + "/" + Application.productName + "_BurstDebugInformation_DoNotShip";
if (Directory.Exists(burstDebugFolder))
{
Directory.Delete(burstDebugFolder, true);
}
var fileName = Application.productName;
if (options["FileName"])
{
fileName = options["FileName"];
}
if (File.Exists(folderPath + $"/../{fileName}.zip"))
{
File.Delete(folderPath + $"/../{fileName}.zip");
}
;
ZipFile.CreateFromDirectory(folderPath, $"./{fileName}.zip");
}
if (buildTarget == BuildTarget.iOS)
{
#if UNITY_IOS
string projectPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj";
UnityEditor.iOS.Xcode.PBXProject pbxProject = new UnityEditor.iOS.Xcode.PBXProject();
pbxProject.ReadFromFile(projectPath);
string target = pbxProject.GetUnityMainTargetGuid();
pbxProject.SetBuildProperty(target, "ENABLE_BITCODE", "NO");
pbxProject.SetBuildProperty(target, "DEBUG_INFORMATION_FORMAT", "dwarf");
if (options["iOSProvisionID"])
{
pbxProject.SetBuildProperty(target, "PROVISIONING_PROFILE", options["iOSProvisionID"]);
}
if (options["iOSProfileSpecifier"])
{
pbxProject.SetBuildProperty(target, "PROVISIONING_PROFILE_SPECIFIER", options["iOSProfileSpecifier"]);
}
if (options["iOSTeamID"])
{
pbxProject.SetBuildProperty(target, "DEVELOPMENT_TEAM", options["iOSTeamID"]);
}
if (options["iOSDistribution"])
{
pbxProject.SetBuildProperty(target, "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "iPhone Distribution");
}
pbxProject.WriteToFile(projectPath);
{
string plistPath = path + "/Info.plist";
PlistDocument plist = new PlistDocument();
plist.ReadFromString(File.ReadAllText(plistPath));
PlistElementDict rootDict = plist.root;
rootDict.SetBoolean("ITSAppUsesNonExemptEncryption", false);
File.WriteAllText(plistPath, plist.WriteToString());
}
#endif
}
}
public static void BuildWindows()
{
PreBuild();
var targetDir = "./build";
if (Directory.Exists(targetDir))
{
Directory.Delete(targetDir, true);
}
if (Directory.Exists(targetDir) == false)
{
Directory.CreateDirectory(targetDir);
}
GenericBuild(targetDir + "/" + Application.productName + ".exe", BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64, BuildOptions.None);
}
}