+ 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!


 + 코드를 작성할 때, 원활한 유지보수를 위하여 모듈화를하여 코드를 작성합니다. 


 + main 함수를 기점으로, Class나 Struct 등과 같이 서로 연관된 것들을 한 곳에 보관하여 관리하는 것이죠.


 + 이렇게 모듈화를 하기 위해선 먼저 연관된 것을을 묶고, 묶은 것들에 대해 *.h 파일*.cpp 파일을 만들어야 합니다.

   - *는 동일한 이름을 가지고 있어야 합니다.


 + *.h 파일에는 선언만 해두고, *.cpp 파일에는 정의를 하면 됩니다.


 + *.h 파일을 작성할 때, 주의해야할 점이 있습니다. 바로 재정의를 방지하기 위한 작업을 해야한다는 것입니다.



<why>

 + 재정의를 방지하는 이유는 파일에서 해당 header파일이 여러번 선언되기 때문입니다.


 + 헤더파일이 나눠져있으면 상관없지 않냐고 할 수 있지만, 그렇지 않습니다. 우리가 컴파일를 하고 빌드를 하게될 때, 문제가 발생하게됩니다.


 + 컴파일을 하게되면, 모든 소스파일이 기계어로 번역이됩니다. 번역이 된 기계어는 서로 *.obj 파일로 변형되어, 빌드 시 서로 연결되어 실행이 되는 것입니다.


 + 컴파일을 할 때, header파일을 선언하게되면, 해당 header파일에 작성된 코드들이 main파일에 그대로 복사가 되어 붙게됩니다. 그렇기에, 여러번 header파일을 선언하게되면, 같은 것들이 중복으로 선언되어 컴파일 에러가 발생하는 것이죠.


 + "중복안되게 코드를 작성하면 되지 않나?" 라고 하실 수 있겠지만... 직접 해보시면 압니다.



<method>

 + 재정의를 막는 방법은 크게 2가지가 있습니다.

1) include guard - 표준

2) pragma once - 비표준



include guard)

 + macro wrapper 방식을 이용하여 재정의를 방지합니다.

 + 표준 방식으로 어느 컴파일러에서도 동작합니다.

 + 해당 header파일을 나타낼 코드를 선언하고, 그 코드가 이전에 선언되지 않았으면 코드를 컴파일합니다.

 + 해당 선언한 코드는 마음대로 작성하셔도 되지만, 일반적인 코딩 Standard에서는 대문자로 작성하는 것을 지향합니다.



pragma once)

 + 이 방법 또한 전처리기를 이용한 재정의 방지법입니다.

 + 비표준으로써, 호환되지 않는 컴파일러도 있습니다.

 + #pragma는 컴파일러 제조회사에서 컴파일러의 기능을 확장시킬 수 있도록 하는 지시자입니다.

 + 표준 컴파일러에서 자신의 컴파일러 제작 기술이 허락하는 대로 최대한의 기능을 제공할 수 있도록 여지를 남겨둔 것으로, 만약 다른 컴파일러에서 해석할 수 없는 pracma를 만나면 그냥 무시하게됩니다.

 + 해당 선언은, 컴파일러에게 해당 header파일이 한 번만 빌드되도록 알려주는 명령어입니다.



*** 참고할 점

 - 이전에는 include guard방식이 매번 정의되어있는지 확인하기에 pragma once보다 작업량이 많았으나, 최신 컴파일러에서는 pragma once처럼 한 번 재정의 판단을 하게되면, 그 다음은 판단을 하지않게되어 성능상 차이가 없어졌다.

 - 좀 더 범용적인 소스를 작성할 땐, include guard를 사용해야하고, 그 이외는 pragma once를 사용하셔도 괜찮을 것입니다.

 - 하지만, 표준을 지향하길 추천드립니다.


** 참고사이트 **

 - http://sarghis.com/blog/941/


Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

 + 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!


 코딩을 하다보면, 라이브러리로 구현된 함수 중, Parameter의 갯수에 상관없이 사용할 수 있는 함수들을 많이 보게됩니다. 대표적으로 printf(...)와 같은 출력문들이 그러한데요, 이러한 함수들은 구현될 때, 모든 경우에 대해서 overloading하는 것이 아닙니다. "Parameter pack"을 이용하여, 함수를 실행시키는 것이죠!!


[Parameter Pack]

 + 이름 그대로 인자들의 묶음을 나타냅니다.


 + 인자들을 묶어서 하나의 인자로 취급하니, 여러 인자를 한 번에 사용할 수 있습니다.


 + Parameter pack은 말 그대로 인자들의 묶음으로, 따로 자르거나 내부를 꺼내어 사용할 수 없습니다. 그냥 그 자체로 사용됩니다.


[Syntax]

'

type...Args

typename | class...Args

template<parameter-list> typename|class...Args

Args...args

'

 + 예시

'

template<class ... Types> struct Tuple {};
Tuple<> t0;           // Types contains no arguments
Tuple<int> t1;        // Types contains one argument: int
Tuple<int, float> t2; // Types contains two arguments: int and float
Tuple<0> error;       // error: 0 is not a type


template<class ... Types> void f(Types ... args);
f();       // OK: args contains no arguments
f(1);      // OK: args contains one argument: int
f(2, 1.0); // OK: args contains two arguments: int and double

'


 + Parameter pack을 사용할 때, 해당 pack 변수는 인자가 없는 상황부터 인지하게 됩니다.

`

template<typename... Args>

void temp(int value, Args... args){...} 

// Can Use : temp(1);, temp(1,2);, temp(1,2,"asdf");

// Can't Use : temp();

`


 + 일단 간단히 사용되는건 이렇고, 좀 더 자세한 것은 날잡아서 더 공부해야할 것 같습니다.


 + printf(...)와 같은 출력문에서 많이 사용된다고 했었는데요, 예시로 한 번 만들어 보겠습니다!

'

#include <iostream>
 
void tprintf(const char* format) // base function
{
    std::cout << format;
}
 
template<typename T, typename... Targs>
void tprintf(const char* format, T value, Targs... Fargs) // recursive variadic function
{
    for ( ; *format != '\0'; format++ ) {
        if ( *format == '%' ) {
           std::cout << value;
           tprintf(format+1, Fargs...); // recursive call
           return;
        }
        std::cout << *format;
    }
}
 
int main()
{
    tprintf("% world% %\n","Hello",'!',123);
    return 0;
}


output : Hello world! 123

'

1) format변수로 나타낼 문장의 위치를 잡습니다. 그리고 value로 다음으로 출력될 변수를 지정하고, 마지막 parameter pack으로 출력될 변수들을 저장하면됩니다.


2) 한 칸씩 전진하면서 구분자를 찾고, 해당 구분자가 나오면 value를 출력해줍니다.


3) value를 출력하고나서는 다음 출력될 변수를 앞으로 당기기 위해 함수를 recursive합니다.


4) 마지막으로, value가 없는 상황을 대비해서 format만 남은 함수를 overloading해줍니다.

   - Overloading을 해주지 않으면, 인자가 하나밖에 없는 상황에선 맞지않는 함수로 인식해 compile error가 발생합니다.


[resursive]

 + 왜 recursive를 해주는지 의아하실 수 있습니다. 그 점을 설명하자면, parameter pack은 그 내부를 하나하나 사용할 수 있는 변수가 아닌, 인수의 집합, 그 자체입니다. 따로 나눌수도 없이, 그냥 어떤 type의 변수들을 가지고 있다는 덩어리죠. 그렇기에 자동적으로 구분해서 사용할 수 있게 만들어야합니다. 그러한 방법으로 recursive를 사용한 것이죠. 위의 함수를 보게되면, recursive를 해주는 부분에 value가 없고 바로 parameter pack이 있습니다. 저렇게 하면 자동으로 parameter pack의 첫 번째 변수가 value로 가게 되는 것이죠. 그림으로 보여드리면

tprintf(1,2,3,4); //format : 1, value : 2, Targs : 3,4

그리고 다음 recursive를 하게 될 때는,

tprintf(1`,3,4); // format : 1`, value : 3, Targs:4

가 됩니다.

즉, 자동으로 parameter pack의 인자들을 하나하나 잘라서 사용하게 되는 것이죠. 이렇기에 recursive를 사용한 것입니다.



*** 참고해야하는 점

 - parameter pack은 따로 내부를 자르거나 꺼내서 사용할 수 없습니다. 그 자체가 변수들을 가지고 있는 덩어리로 취급됩니다.




Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

 + 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!


Slider는 Progress Bar를 사용하기 위한 중요한 요소로서, 변화되는 값에 따라 보여지는 Image가 달라지게 합니다. 대부분 게임에서 체력, 마나, 스태미너와 같은 게이지를 보여주기 위해 사용되죠.


** Slider가 가지고 있는 Properties는 공식 Manuel을 확인해주세요!

Korhttps://docs.unity3d.com/kr/current/Manual/script-Slider.html

Enghttps://docs.unity3d.com/ScriptReference/UI.Slider.html



Slider를 사용할 때, 가장 중요한 부분은 "OnValueChanged" Event입니다.


[OnValueChanged]

 + Slider로 나타내는 Value가 변했을 때, 어떤 식으로 처리를 해줘야 하는지에 대한 정보를 입력하는 곳입니다.

 + Slider를 사용함에 있어, 가장 중요한 부분이라고도 할 수 있습니다.

 + 해당 Event를 사용하기 위한 방법으로는 크게 2가지가 있습니다.

  1) delegate를 넘겨주기.

 - 등록할 Event함수에 매개변수가 있어도 상관없으나, 어차피 대부분 Script내부의 값을 가져와 사용하는 것이므로, 굳이 매개변수를 쓸 필요는 없다고 생각한다.



  2) 함수이름 넘겨주기.

 - Event로 등록할 함수는 반드시 Float형 변수 하나를 매개변수로 가지고 있어야 합니다.



 - Slider를 사용하기위한 Unity 공식 문법입니다.

 - 해당 매개변수는 변화된 값을 나타냅니다.



[Slide 시, Image Control]

 + Value가 변해 Slider가 움직여 해당 Image가 변할 때, Image type에 따라 어떻게 변하는지 달라집니다.

 + 여러 Image type이 있지만, 일반적으로 Progress Bar를 위해 사용되는 type은 Filled입니다.

 + Simple을 하게되면, 슬라이드된 만큼 이미지가 축소되어 보이게됩니다.

 


 + Filled를 하게되면, 슬라이드된 만큼 이미지가 사라져 보이게 됩니다. - 우리가 원하는 모습.

 

  <변경하는 법>

 + (Hierarchy에서) Progress Bar -> Fill Area -> Fill -> Image -> Image Type





Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

+ Recent posts