System.Version클래스를 이용해 시멘틱 버전을 관리한다.
C# System.Version 문서를 보면 다음과 같은 내용이 나온다.
더보기
버전 번호는 주 버전, 부 버전, 빌드 버전 및 수정 버전의 구성 요소로 구성 됩니다. 주 및 보조 구성 요소가 필요 합니다. 빌드 및 수정 구성 요소는 선택 사항 이지만 수정 구성 요소가 정의 되어 있으면 빌드 구성 요소가 필요 합니다. 정의 된 모든 구성 요소는 0 보다 크거나 같은 정수 여야 합니다. 버전 번호의 형식은 다음과 같습니다. 선택적 구성 요소는 대괄호 ([및])로 표시 됩니다.
주. minor[.빌드[.수정 버전]]
구성 요소는 규칙에 따라 다음과 같이 사용 됩니다.
- Major: 이름은 같지만 주 버전이 다른 어셈블리는 교환할 수 없습니다. 버전 번호가 높으면 이전 버전과의 호환성을 가정할 수 없는 제품의 주요 재작성이 표시 될 수 있습니다.
- Minor: 두 어셈블리의 이름과 주 버전 번호가 동일 하지만 부 버전 번호가 다른 경우 이전 버전과의 호환성을 위해 크게 향상 된 기능을 나타냅니다. 이 버전의 부 버전 번호는 제품의 시점 릴리스 또는 완전히 이전 버전의 제품 버전을 나타낼 수 있습니다.
- 빌드: 빌드 번호의 차이는 동일한 소스의 재컴파일를 나타냅니다. 프로세서, 플랫폼 또는 컴파일러가 변경 될 때 다른 빌드 번호를 사용할 수 있습니다.
- 수정 버전: 같은 이름, 주 버전 및 부 버전 번호가 있지만 수정 버전이 다른 어셈블리는 완전히 교환할 수 있도록 설계 되었습니다. 이전에 릴리스된 어셈블리에서 보안 허점을 해결 하는 빌드에 사용 될 수 있는 수정 번호가 더 높습니다.
버전 관리
namespace Waker.BuildTools
{
public class VersionUpdater : ScriptableObject
{
[SerializeField] private int major;
[SerializeField] private int minor;
[SerializeField] private int build;
public Version GetVersion()
{
return new System.Version(major, minor, build);
}
// 빌드 버전을 증가시키고 유니티 플레이어 셋팅에 적용
private void IncreaseBuild()
{
build++;
UpdatePlayerSettings();
}
// 버전을 플레이어 셋팅에 적용
public void UpdatePlayerSettings()
{
PlayerSettings.bundleVersion = GetVersion().ToString(3);
// 안드로이드일 경우 번들 버전도 같이 증가
#if UNITY_ANDROID
PlayerSettings.Android.bundleVersionCode = build;
#endif
}
}
}
IncreaseBuild를 호출하여 빌드 버전을 자동으로 증가시킬 수 있다.
빌드 후 버전 자동 증가
internal static VersionUpdater GetOrCreateSettings()
{
var settings = AssetDatabase.LoadAssetAtPath<VersionUpdater>(CustomSettingsPath);
if (settings == null)
{
settings = ScriptableObject.CreateInstance<VersionUpdater>();
settings.major = 1;
settings.minor = 1;
settings.build = 0;
AssetDatabase.CreateAsset(settings, CustomSettingsPath);
AssetDatabase.SaveAssets();
}
return settings;
}
[PostProcessBuildAttribute(1)]
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
{
var i = GetOrCreateSettings();
i.IncreaseBuild();
EditorUtility.SetDirty(i);
}
PostProcessBuildAttribute를 이용해 빌드 작업 후 빌드 버전을 자동으로 증가시킬 수 있다.
프로젝트 셋팅
internal static SerializedObject GetSerializedSettings()
{
return new SerializedObject(GetOrCreateSettings());
}
[SettingsProvider]
public static SettingsProvider CreateSettingsProvider()
{
// First parameter is the path in the Settings window.
// Second parameter is the scope of this setting: it only appears in the Project Settings window.
var provider = new SettingsProvider("Project/Waker/Version Updater", SettingsScope.Project)
{
// By default the last token of the path is used as display name if no label is provided.
label = "Version Updater",
// Create the SettingsProvider and initialize its drawing (IMGUI) function in place:
guiHandler = (searchContext) =>
{
var settings = VersionUpdater.GetSerializedSettings();
settings.Update();
EditorGUILayout.PropertyField(settings.FindProperty("major"), new GUIContent("major"));
EditorGUILayout.PropertyField(settings.FindProperty("minor"), new GUIContent("minor"));
EditorGUILayout.PropertyField(settings.FindProperty("build"), new GUIContent("build"));
settings.ApplyModifiedProperties();
if (GUILayout.Button("Version Update"))
{
VersionUpdater.GetOrCreateSettings().UpdatePlayerSettings();
}
},
// Populate the search keywords to enable smart search filtering and label highlighting:
// keywords = new HashSet<string>(new[] { "Number", "Some String" })
};
return provider;
}
SettingsProvider를 이용해 프로젝트 셋팅에서 값을 설정할 수 있다.
전체 코드
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
namespace Waker.BuildTools
{
public class VersionUpdater : ScriptableObject
{
public const string CustomSettingsPath = "Assets/Editor/Version Updater.asset";
[SerializeField] private int major;
[SerializeField] private int minor;
[SerializeField] private int build;
public Version GetVersion()
{
return new Version(major, minor, build);
}
private void IncreaseBuild()
{
build++;
UpdatePlayerSettings();
}
public void UpdatePlayerSettings()
{
PlayerSettings.bundleVersion = GetVersion().ToString(3);
#if UNITY_ANDROID
PlayerSettings.Android.bundleVersionCode = build;
#endif
}
internal static VersionUpdater GetOrCreateSettings()
{
var settings = AssetDatabase.LoadAssetAtPath<VersionUpdater>(CustomSettingsPath);
if (settings == null)
{
settings = ScriptableObject.CreateInstance<VersionUpdater>();
settings.major = 1;
settings.minor = 1;
settings.build = 0;
AssetDatabase.CreateAsset(settings, CustomSettingsPath);
AssetDatabase.SaveAssets();
}
return settings;
}
internal static SerializedObject GetSerializedSettings()
{
return new SerializedObject(GetOrCreateSettings());
}
[PostProcessBuildAttribute(1)]
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
{
var i = GetOrCreateSettings();
var prevVersion = i.GetVersion();
i.IncreaseBuild();
EditorUtility.SetDirty(i);
Debug.Log($"VersionUpdater Previous Version is {prevVersion}, Current Version is {i.GetVersion()}.");
}
[SettingsProvider]
public static SettingsProvider CreateSettingsProvider()
{
// First parameter is the path in the Settings window.
// Second parameter is the scope of this setting: it only appears in the Project Settings window.
var provider = new SettingsProvider("Project/Waker/Version Updater", SettingsScope.Project)
{
// By default the last token of the path is used as display name if no label is provided.
label = "Version Updater",
// Create the SettingsProvider and initialize its drawing (IMGUI) function in place:
guiHandler = (searchContext) =>
{
var settings = VersionUpdater.GetSerializedSettings();
settings.Update();
EditorGUILayout.PropertyField(settings.FindProperty("major"), new GUIContent("major"));
EditorGUILayout.PropertyField(settings.FindProperty("minor"), new GUIContent("minor"));
EditorGUILayout.PropertyField(settings.FindProperty("build"), new GUIContent("build"));
settings.ApplyModifiedProperties();
if (GUILayout.Button("Version Update"))
{
VersionUpdater.GetOrCreateSettings().UpdatePlayerSettings();
}
},
// Populate the search keywords to enable smart search filtering and label highlighting:
// keywords = new HashSet<string>(new[] { "Number", "Some String" })
};
return provider;
}
}
}