유니티 쓰레드(Task)사용 시 메인쓰레드에서 호출되도록 하는 방법

카테고리 없음|2021. 5. 13. 11:23

Task를 실행 후 ContinueWith로 콜백을 실행할 때 두번째 인자로 TaskScheduler.FromCurrentSynchronizationContext()를 넘겨주면 메인쓰레드에서 실행한다.

 

별도의 MainthreadDispatcher를 사용하지 않아도 된다.

 

댓글()

유니티 안드로이드 키스토어 비밀번호 자동 입력

카테고리 없음|2021. 5. 7. 16:02

Project Settings 윈도우에서 비밀번호를 입력할 수 있으며, 유니티를 끄고 켜도 입력이 유지된다.

#if UNITY_ANDROID
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;

namespace Waker.BuildTools
{
    public partial class AndroidKeystore : ScriptableObject
    {
        public const string CustomSettingsPath = "Assets/Editor/Android Keystore Password.asset";

        [SerializeField] private string keystorePassword;
        [SerializeField] private string keyaliasPassword;

        public void UpdatePlayerSettings()
        {
            var i = GetOrCreateSettings(); 

            PlayerSettings.Android.keystorePass = i.keystorePassword;
            PlayerSettings.Android.keyaliasPass = i.keyaliasPassword;
        }

        internal static AndroidKeystore GetOrCreateSettings()
        {
            var settings = AssetDatabase.LoadAssetAtPath<AndroidKeystore>(CustomSettingsPath);
            if (settings == null)
            {
                settings = ScriptableObject.CreateInstance<AndroidKeystore>();
                AssetDatabase.CreateAsset(settings, CustomSettingsPath);
                AssetDatabase.SaveAssets();
            }
            return settings;
        }

        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/Android Keystore Password", SettingsScope.Project)
            {
                // By default the last token of the path is used as display name if no label is provided.
                label = "Android Keystore Password",
                // Create the SettingsProvider and initialize its drawing (IMGUI) function in place:
                guiHandler = (searchContext) =>
                {
                    var settings = AndroidKeystore.GetSerializedSettings();

                    settings.Update();

                    EditorGUILayout.PropertyField(settings.FindProperty("keystorePassword"), new GUIContent("keystorePassword"));
                    EditorGUILayout.PropertyField(settings.FindProperty("keyaliasPassword"), new GUIContent("keyaliasPassword"));

                    settings.ApplyModifiedProperties();

                    if (GUILayout.Button("Update"))
                    {
                        AndroidKeystore.GetOrCreateSettings().UpdatePlayerSettings();
                    }
                },

                // Populate the search keywords to enable smart search filtering and label highlighting:
                // keywords = new HashSet<string>(new[] { "Number", "Some String" })
            };

            return provider;
        }
    }
}
#endif

댓글()

유니티 빌드 시 버전 관리

카테고리 없음|2021. 5. 7. 15:49

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;
        }
    }
}

댓글()