Unity Scriptable Build Pipeline — 커스텀 빌드 자동화
Scriptable Build Pipeline(SBP)은 Unity의 빌드 파이프라인을 C# 코드로 완전히 제어할 수 있는 패키지입니다. Addressables가 내부적으로 SBP를 사용하며, 커스텀 빌드 단계 삽입, 증분 빌드(incremental build), 빌드 캐시 등을 지원합니다.
1. 설치
섹션 제목: “1. 설치”Package Manager → Unity Registry →Scriptable Build Pipeline → Install2. 기본 AssetBundle 빌드
섹션 제목: “2. 기본 AssetBundle 빌드”using UnityEditor;using UnityEditor.Build.Pipeline;using UnityEngine;
public static class BuildScript{ [MenuItem("Build/Build AssetBundles (SBP)")] public static void BuildBundles() { var bundleBuilds = ContentBuildInterface.GenerateAssetBundleBuilds();
var buildParams = new BundleBuildParameters( EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettings.selectedBuildTargetGroup, "Assets/StreamingAssets/Bundles");
// 증분 빌드 캐시 활성화 buildParams.UseCache = true; buildParams.CacheServerHost = "cache.example.com"; buildParams.CacheServerPort = 8126;
var content = new BundleBuildContent(bundleBuilds); var result = ContentPipeline.BuildAssetBundles( buildParams, content, out var manifest);
if (result >= ReturnCode.Success) Debug.Log($"빌드 성공: {manifest.GetAllAssetBundles().Length}개 번들"); else Debug.LogError($"빌드 실패: {result}"); }}3. 커스텀 빌드 태스크 삽입
섹션 제목: “3. 커스텀 빌드 태스크 삽입”using UnityEditor.Build.Pipeline;using UnityEditor.Build.Pipeline.Interfaces;using UnityEditor.Build.Pipeline.Utilities;
// 커스텀 빌드 태스크 정의public class LogBuildTask : IBuildTask{ public int Version => 1;
public ReturnCode Run() { var context = BuildContext.GetContextObject<IBundleBuildContent>(); Debug.Log($"[Build] 빌드 시작: {context.BundleLayout.Count}개 번들"); return ReturnCode.Success; }}
// 빌드 태스크 파이프라인 커스터마이징public static class CustomBuildPipeline{ public static ReturnCode BuildWithCustomTasks() { // 기본 태스크 목록 가져오기 var tasks = DefaultBuildTasks.Create( DefaultBuildTasks.Preset.AssetBundleBuiltInShaderExtraction);
// 시작 전 커스텀 태스크 삽입 tasks.Insert(0, new LogBuildTask());
var buildParams = new BundleBuildParameters( BuildTarget.StandaloneWindows64, BuildTargetGroup.Standalone, "Assets/StreamingAssets/Bundles");
var content = new BundleBuildContent( ContentBuildInterface.GenerateAssetBundleBuilds());
return ContentPipeline.BuildAssetBundles( buildParams, content, out _, tasks); }}4. 플레이어 빌드 자동화
섹션 제목: “4. 플레이어 빌드 자동화”using UnityEditor;using UnityEditor.Build.Reporting;using System;
public static class PlayerBuildScript{ // CI/CD에서 호출 public static void BuildFromCommandLine() { var args = Environment.GetCommandLineArgs(); string outputPath = GetArg(args, "-outputPath") ?? "Builds/Game"; string version = GetArg(args, "-version") ?? "1.0.0";
PlayerSettings.bundleVersion = version;
var options = new BuildPlayerOptions { scenes = GetEnabledScenes(), locationPathName = outputPath, target = BuildTarget.StandaloneWindows64, options = BuildOptions.None, };
var report = BuildPipeline.BuildPlayer(options);
if (report.summary.result == BuildResult.Succeeded) { Console.WriteLine($"[BUILD] 성공: {report.summary.totalSize / 1024 / 1024} MB"); EditorApplication.Exit(0); } else { Console.WriteLine($"[BUILD] 실패: {report.summary.totalErrors} 오류"); EditorApplication.Exit(1); } }
static string[] GetEnabledScenes() { return Array.ConvertAll( EditorBuildSettings.scenes, s => s.path); }
static string? GetArg(string[] args, string name) { for (int i = 0; i < args.Length - 1; i++) if (args[i] == name) return args[i + 1]; return null; }}5. BuildReport 분석
섹션 제목: “5. BuildReport 분석”using UnityEditor.Build.Reporting;
public static class BuildAnalyzer{ [MenuItem("Build/Analyze Last Build")] static void Analyze() { var report = BuildReport.GetLatestReport(); if (report == null) { Debug.LogError("빌드 리포트 없음"); return; }
Debug.Log($"빌드 시간: {report.summary.totalTime.TotalSeconds:F1}초"); Debug.Log($"빌드 크기: {report.summary.totalSize / 1024 / 1024} MB");
// 가장 큰 에셋 Top 10 var files = report.GetFiles(); Array.Sort(files, (a, b) => b.size.CompareTo(a.size));
Debug.Log("=== Top 10 큰 에셋 ==="); for (int i = 0; i < Math.Min(10, files.Length); i++) Debug.Log($"{files[i].size / 1024} KB {files[i].path}"); }}6. CI/CD 커맨드라인 실행
섹션 제목: “6. CI/CD 커맨드라인 실행”# GitHub Actions / Jenkins에서 Unity 빌드Unity \ -batchmode \ -nographics \ -projectPath /path/to/project \ -executeMethod PlayerBuildScript.BuildFromCommandLine \ -outputPath Builds/Game \ -version 1.2.3 \ -logFile build.log \ -quit7. 증분 빌드 캐시 설정
섹션 제목: “7. 증분 빌드 캐시 설정”// Unity Accelerator 또는 로컬 캐시 서버 연동var buildParams = new BundleBuildParameters(...);buildParams.UseCache = true;buildParams.CacheServerHost = Environment.GetEnvironmentVariable("CACHE_SERVER") ?? "localhost";buildParams.CacheServerPort = 8126;Scriptable Build Pipeline은 빌드를 코드로 제어하고, 태스크를 삽입하며, 증분 빌드로 시간을 줄이는 데 핵심입니다. CI/CD에서 -executeMethod로 빌드 스크립트를 호출하고 BuildReport로 크기와 시간을 모니터링하면 빌드 파이프라인의 완전한 자동화가 가능합니다.