Jenkins 및 기타 등등으로 자동 빌드를 하기 위해서 필수적으로 들어가는 Command Line

Unity에서도 Command Line을 지원해주고 있습니다.


근데 이걸 어느 컬럼에 써야 될지 난감하긴 하네요.... 주된 내용이 C#이니 그리고 활용은 Unity뿐만 아니라 Command Line에서 사용 가능하니 C# 컬럼에서 작성하겠습니다.


기본적으로 Unity에서 Command Line을 지원하는데 그에 대한 정보는 

https://docs.unity3d.com/kr/current/Manual/CommandLineArguments.html 에 참조하시면 됩니다.


Jenkins에서는 기본적으로 plugin을 제공해주고 있고, 이부분은 다음에 설명을 하도록 하고 대충 사용 방법을 설명하면 이렇게 사용합니다.

 - Mac 기준

{유니티설치경로}/Unity.app/Contents/MacOS/Unity -quit -batchMode - buildTarget Android -projectPath 프로젝트경로 -excuteMethod 클래스명.함수명


프로젝트 경로가 Users/Dosinamja/project 이고 사용하는 함수가 AutoBuilder.BuildAndroid라고 했을 경우에는 다음과 같습니다.


/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit -batchMode -buildTarget Android -projectPath Users/Dosinamja/project -excuteMethod AutoBuilder.BuildAndroid


대충 이런식으로 사용됩니다.


이렇게 하면 Command Line 으로 빌드를 수행할수 있긴 하지만 사용하다가 보면 명령인자를 넘겨줘서 처리하고 싶을 경우가 많이 생깁니다. 그렇다고 매번 소스를 수정한 뒤에 빌드를 수행하기에는 매우 번거롭고 생산적이지 못하지요.


그래서 실질적으로 arguments 를 넘겨줘서 원하는 작업을 수행하기 위해서 작업이 필요합니다.

기본적으로 명령인자를  parsing 하여 우리가 원하는 값들을 뽑아내서 사용한다고 생각하면 된됩니다.


기본적인 코드는 GitHub에 올라와 있습니다.( 물론 제가 만든것은 아닙니다. )

https://github.com/EpixCode/CommandLineCustomArguments/blob/master/Assets/Scripts/Com/EpixCode/Util/CommandLineReader.cs#L76


#region Using

using System;

using System.Collections.Generic;

using System.Linq;

using UnityEngine;

#endregion


public class CommandLineReader

{

    //Config

    private const string CUSTOM_ARGS_PREFIX = "-CustomArgs:";

    private const char CUSTOM_ARGS_SEPARATOR = ';';


    public static string[] GetCommandLineArgs()

    {

        return Environment.GetCommandLineArgs();

    }


    public static string GetCommandLine()

    {

        string[] args = GetCommandLineArgs();

        if (args.Length > 0)

        {

            return string.Join(" ", args);

        }

        else

        {

            Debug.LogError("CommandLineReader.cs - GetCommandLine() - Can't find any command line arguments!");

            return "";

        }

    }


    public static Dictionary<string,string> GetCustomArguments()

    {

        Dictionary<string, string> customArgsDict = new Dictionary<string, string>();

        string[] commandLineArgs = GetCommandLineArgs();

        string[] customArgs;

        string[] customArgBuffer;

        string customArgsStr = "";


        try

        {

            customArgsStr = commandLineArgs.Where(row => row.Contains(CUSTOM_ARGS_PREFIX)).Single();

        }

        catch (Exception e)

        {

            Debug.LogError("CommandLineReader.cs - GetCustomArguments() - Can't retrieve any custom arguments in the command line [" + commandLineArgs + "]. Exception: " + e);

            return customArgsDict;

        }


        customArgsStr = customArgsStr.Replace(CUSTOM_ARGS_PREFIX, "");

        customArgs = customArgsStr.Split(CUSTOM_ARGS_SEPARATOR);


        foreach (string customArg in customArgs)

        {

            customArgBuffer = customArg.Split('=');

            if (customArgBuffer.Length == 2)

            {

                customArgsDict.Add(customArgBuffer[0], customArgBuffer[1]);

            }

            else

            {

                Debug.LogWarning("CommandLineReader.cs - GetCustomArguments() - The custom argument [" + customArg + "] seem to be malformed.");

            }

        }


        return customArgsDict;

    }


    public static string GetCustomArgument(string argumentName)

    {

        Dictionary<string, string> customArgsDict = GetCustomArguments();


        if (customArgsDict.ContainsKey(argumentName))

        {

            return customArgsDict[argumentName];

        }

        else

        {

            Debug.LogError("CommandLineReader.cs - GetCustomArgument() - Can't retrieve any custom argument named [" + argumentName + "] in the command line [" + GetCommandLine() + "].");

            return "";

        }

    }

}



사용방법은 다음과 같습니다.



/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit -batchMode -buildTarget Android -projectPath Users/Dosinamja/project -excuteMethod AutoBuilder.BuildAndroid -CustomArgs:Language=en_US;Version=1.02


이런식으로 인자를 붙여서 CommandLine 을 사용하면 됩니다.


.cs파일에서는 


public class AutoBuilder

{

static void BuildAndroid

{

string language = string.Empty;

language = CommandLineReader.GetCustomArgument("Language");

if( String.IsNullOrEmpty(language) == false && language == "en_US" )

{

// 해당 코드 수행.

}


string version = string.Empty;

version = CommandLineReader.GetCustomArgument("Version");

if( String.IsNullOrEmpty(version) == false && version == "1.02" )

{

// 해당 코드 수행.

}

}

}


이런식으로 작업하면 됩니다.

또 다른 방법으로는 매번 CustomArgs: 를 설정하기 싫으시면 BuildAndroid()함수를 호출하기 전에 명령인자를 죄다 저장한뒤에 특정 문자열 키를 저장하고 그 해당 키값을 가져쓰는 방식으로 사용하면 됩니다.


static void BuildAndroid

{

InitCommandLineArgs();

}


static private void InitCommandLineArgs()

{

string[] commandArgs;

commandArgs = Environment.GetCommandLineArgs();


for( int i = 0; i < commandArgs.Length; ++i )

{

// 명령인자 매개변수 앞에 특정 문자열을 파싱해서

// 해당하는 매개변수 명을 키값으로 하는 Dictionary 설정.

// 나중에 Dictionary에서 특정 키값으로 하는 값을 가져옴.

}

}


이렇게 사용하면 가능합니다. CommandLine을 좀 더 유연하게 사용하여 원하시는 작업 하시길 바랍니다.

'프로그래밍 > C#' 카테고리의 다른 글

partial classes  (0) 2016.11.21
JsonFx 파일 가독성 높게 저장하기  (0) 2016.11.21

기본적으로 C#에서 사용하는 Json Library는 여러종류가 있지만( 일단 알고 있는 종류는 몇개 안됨...) JsonFx에서 제대로 설정을 하지 않고 파일을 저장하면 One Line(!!!)으로 저장되는 경우가 있다. MB 단위로 파일이 저장됐는데 One Line으로 나오면... ㅠㅠ

JsonFx 에서 개행단위로 저장되는 옵션이다.


using (StreamWriter writer = File.CreateText(txtFilePath))

{

            JsonFx.Json.JsonWriter cJsonWriter = new JsonFx.Json.JsonWriter(writer);

            cJsonWriter.Settings.PrettyPrint = true;

            cJsonWriter.Write(Info);   // 저장하는 Json 포맷

}

'프로그래밍 > C#' 카테고리의 다른 글

Command Line Reader 클래스  (0) 2016.11.21
partial classes  (0) 2016.11.21

Unity performs many operations once per frame, including:

  • Input processing

  • Main update (including Update())

  • Main coroutine updates (including yield return null)

  • Late update (including LateUpdate())

  • Scene rendering (quite a few steps)

  • Gizmo/UI rendering

  • End of frame (including WaitForEndOfFrame)

One returns just before rendering, the other returns just after (but just before the frame is displayed). When the difference isn't important, I usually use and recommend yield return null, as it's closer to the way other Update and coroutine functions work.

+ Recent posts