우선 트랜스폼 컴포넌트는 게임 오브젝트에 필수로 부착되는 컴포넌트로, 인스펙터 뷰에서 보면 [그림 1]과 같이 Vector3 형식의 포지션(Position), 로테이션(Rotation), 스케일(Scale) 프로퍼티를 사용자에게 공개하고 있다.
프로퍼티의 이름에 맞게 포지션 프로퍼티는 게임 오브젝트의 위치 정보를 수정할 수 있다.
로테이션 프로퍼티는 회전 정보를 가지고 이를 수정할 수 있다.
스케일 프로퍼티는 크기 정보에 관여한다.
이렇게 인스펙터 뷰에서 보이는 트랜스폼 컴포넌트로 씬 안에 있는 게임 오브젝트의 위치를 옮기거나, 회전시키고, 그 크기를 바꿀 수 있다. 하지만 인스펙터 뷰에서 트랜스폼 컴포넌트의 내용을 변경하는 것은 게임 중에는 불가능한 일로 고정된 건물이나 물건같은 오브젝트에나 사용할 수 있는 방법이다.
플레이어, 몬스터와 같은 캐릭터, 총알, 화살 같은 투사체, 말, 자동차 같은 탈 것처럼 게임 안에서 플레이어의 조작이나 AI의 조작을 따라서 움직일 게임 오브젝트들은 스크립트를 이용해서 이동시켜야 한다.
스크립트로 트랜스폼 컴포넌트 다루기
트랜스폼 컴포넌트 접근하기
public class TransformController : MonoBehaviour
{
void Start()
{
Transform myTransformComponent = transform;
}
}
커스텀 컴포넌트가 부착된 게임 오브젝트의 트랜스폼 컴포넌트를 가져오기 위해서는 모노비헤이비어(MonoBehaviour) 클래스를 통해서 상속받은 transform 프로퍼티를 호출하면 된다.
transform 프로퍼티를 어디서 상속받는지 궁금할 수도 있다. 그럴 때는 트랜스폼 컨트롤러 클래스가 상속받는 모노비헤이비어 클래스를 클릭하고 F12키를 눌러서 모노비헤이비어 클래스 파일로 이동한 다음, 같은 과정을 컴포넌트(Component) 클래스가 나올 때까지 반복하면 된다. 그러면 컴포넌트 클래스에 정의된 transform 프로퍼티를 확인할 수 있다.
위치 이동시키기
position으로 직접 이동시키기
그럼 제일 먼저 트랜스폼 컴포넌트를 이용해서 게임 오브젝트를 이동시켜보자.
public void MovePosition(Vector3 newPosition)
{
transform.position = newPosition;
}
게임 오브젝트의 위치 정보를 다루는 포지션 프로퍼티에 접근하기 위해서는 위의 예시 코드와 같이 transform.position을 이용하면 된다.
public void MovePositionUseTranslate(Vector3 moveDirection)
{
transform.Translate(moveDirection);
}
Translate() 함수는 position 프로퍼티에 직접 위치를 집어넣어서 이동시키는 것과는 달리 게임 오브젝트가 이동하고자 하는 방향과 속력인 벡터를 매개변수로 받아 그 벡터의 방향과 길이만큼 게임 오브젝트를 이동시키는 함수이다.
위 코드를 저장하고 플레이해보면 position을 이용한 오브젝트 이동에서는 1 ~ -1 사이에서만 움직이던 것과는 달리 Translate() 함수를 이용한 이동에서는 훨씬 큰 폭으로 움직이는 것을 볼 수 있다. 이것은 이동 방향 벡터가 코사인 그래프를 따라서 바뀌는 동안에 0보다 값이 커지면 위로, 0보다 작아지면 아래로 움직이기 때문이다.
두 이동 방식을 비교하기 위해서 TransformController를 상속받는 두 클래스를 만들어보았다. PositionMover 클래스는 매 프레임 MovePosition() 함수를 호출해서 (0, 0.1, 0) 벡터를 넣어주고, TranslateMover 클래스는 매 프레임 MovePositionUseTranslate() 함수를 호출해서 역시 같은 벡터를 넣어주고 있다.
에디터로 돌아가서 게임 오브젝트 두 개를 만들고 이 두 컴포넌트를 각각 붙여주고 플레이하면 TranslateMover 컴포넌트를 붙인 게임 오브젝트만 저 멀리 올라가버리는 것을 볼 수 있다. 하지만 PositionMover 컴포넌트를 붙인 게임 오브젝트는 시작되는 순간에 (0, 0.1, 0) 좌표로만 이동한 다음에 그대로 움직이지 않는 것을 보면, 두 방법의 차이를 이해할 수 있다.
회전시키기
rotation으로 회전시키기
void Start()
{
transform.rotation = new Quaternion();
}
게임 오브젝트를 회전시키기 위해서는 transform.rotation 프로퍼티를 사용하면 된다. 다만, 인스펙터 뷰에서 공개된 Rotation 프로퍼티가 Vector3 형식인 것과 달리 스크립트에서는 쿼터니언(Quaternion) 구조체를 사용한다.
Quaternion rotation = new Quaternion();
rotation.w
rotation.x
rotation.y
rotation.z
쿼터니언 구조체는 벡터와는 다른 사원수라는 체계를 사용해서 오브젝트의 회전을 표현한다. 이 사원수라는 체계는 상당히 난해한 체계이기 때문에 유니티의 공식 문서에서는 사원수에 대한 지식을 충분히 가지고 있지 않다면 쿼터니언을 직접 수정하지 않도록 권장하고 있다.
그럼 사원수를 제대로 알지 못하면 게임 오브젝트를 회전시키지 못하게 되는가? 그렇지는 않다. 인스펙터 뷰에서처럼 3차원 벡터를 이용해서 회전을 다루는 방법을 오일러 각 체계(Euler angle system)라고 부른다. 오일러 각 체계 이용하면 xyz 각 축을 기준으로 오브젝트가 얼마나 회전한 상태인지 직관적으로 알 수 있다. 그래서 쿼터니언 구조체에는 이 오일러 각 체계의 회전을 사원수 체계의 회전으로 전환해주는 Euler() 함수가 포함되어 있다. 이 함수를 이용하면 Vector3로 표현된 각을 Quaternion으로 변환할 수 있다.
그리고 회전 역시 이동과 마찬가지로 rotation 프로퍼티를 직접 수정하는 방법과 Rotate() 함수를 사용하는 방법 두 가지가 있다. 그리고 그 차이점 역시 이동시키기에서의 position 직접 이동과 Translate() 함수를 이용한 이동과 비슷하다.
벡터에 대해서 수학이나 물리학에서는 여러 복잡한 정의가 존재하는데 간단하게 요약하자면 특정한 공간에서의 방향과 크기를 표현하는 도구로서 주로 화살표로 표시되는 개념이다.
[그림 1]을 예시로 들면 오른쪽으로 뻗어나가는 X축과 위쪽으로 뻗어나가는 Y축, 두 개의 축으로 구성된 2차원 평면 공간이 있고, (2, 2) 위치를 가리키고 있는 V1 벡터와 (-1, -2) 위치를 가리키고 있는 V2 벡터, 두 개의 벡터가 2차원 공간 속에 존재하는 것을 볼 수 있다.
즉, 여기서는 2차원 평면이 "특정한 공간"이며, 벡터는 그 공간 안에서 방향과 크기를 표현하는 도구라고 말했듯이, 벡터를 표시한 화살표를 보는 것만으로도 이 벡터가 어느 방향을 가리키고 있고 얼마만큼의 길이를 가지는지 알 수 있다.
그리고 이 "특정한 공간"은 몇 차원이든 가능하지만 대부분은 사람이 쉽게 인지할 수 있는 2차원 혹은 3차원으로 정의된다. 유니티에서도 2차원과 3차원의 벡터만 사용한다.
벡터의 활용
벡터는 방향과 크기를 표현하는 도구라고 이야기했는데, 이것을 이용해 여러 가지 용도로 활용된다.
첫 번째 활용법은 방향이다. [그림 1]과 같이 평면에 벡터가 표시하는 좌표까지 화살표를 그리는 것으로 방향을 쉽게 알 수 있다.
두 번째 활용법은 속도이다. V1과 V2가 [그림 1]에서는 서로 다른 방향을 가리키고 있는데, [그림 2]와 같이 두 벡터를 같은 방향으로 놓고 보면, V1이 V2보다 긴 것을 확인할 수 있다. 1초 동안 각 벡터의 길이만큼 이동한다고 가정하면, 당연히 같은 시간동안 V1만큼 이동한 것이 V2만큼 이동한 것보다 멀리 이동할 수 있고, 벡터의 방향 자체가 이동 방향의 의미를 가지기 때문에, 이동하고자하는 방향과 속력, 즉, 속도의 개념으로 활용되는 것이다.
세 번째 활용법은 좌표이다. [그림 1]에서 X축과 Y축이 교차하는 지점을 공간의 중심이라고 가정했을 때, V1 위치에 어떤 오브젝트가 있다면, 그 오브젝트는 공간의 중심으로부터 (2, 2)의 위치에 있다고 말할 수 있다.
벡터의 계산
벡터에 대한 여러가지 계산들이 존재하는데 이러한 계산 방법들을 잘 활용하면 게임의 기능을 구현하는데 유용하게 사용할 수 있다.
벡터의 덧셈과 뺄셈
두 개의 벡터는 서로 더하거나 뺄 수 있다.
우선 벡터의 덧셈을 살펴보자. [그림 3]을 보면 (1, 2)의 V1과 (2, 1)의 V2를 더하면 (3, 3)의 V3가 나오는 것을 볼수 있다. V1 지점에서 V2 만큼 이동했다고 여기면 된다.
또 다른 관점에서 살펴보면 두 벡터의 합은 서로 다른 방향의 두 힘이 충돌했을 때의 그 합쳐진 힘의 진행 방향으로 해석될 수도 있다.
벡터의 뺄셈은 역시 (1, 2)인 V1에서 (2, 1)인 V2를 빼면 (-1, 1)인 V3가 나온다. 다만 여기서 기억할 점은 이렇게 결과 값으로 나온 V3가 V2 지점에서 시작하여 V1 방향으로 이동하는 V3'와 길이와 방향이 모두 같다는 것이다. 이것을 이용하면 V1과 V2 사이의 거리, V2에서 V1으로 가는 방향등을 구할 수 있다.
벡터와 스칼라의 곱셈
벡터는 좌표로서 공간 상에서 방향과 크기를 의미하지만 스칼라는 크기 만을 가지는 값이다. 벡터가 차원 축을 따라서 (2, 0), (1, 2, 3)과 같은 값을 가지는 것에 비해 1, 10, 24 등의 단일한 값을 의미한다.
(1, 1)인 V1에 4인 스칼라 S를 곱하면 V1의 각 원소에 S를 곱하여 (4, 4)인 V2를 얻게 된다. 이렇게 벡터에 스칼라를 곱하는 계산은 주로 벡터의 크기를 원하는대로 늘이거나 줄이는 등의 계산이나, 벡터에 -1을 곱해서 현재 벡터의 반대 방향을 구하는데 주로 사용된다.
벡터의 길이
[그림 2]에서는 벡터를 나란히 놓는 원시적인 방식으로 벡터의 길이를 비교했다. 이런 방식 외에 계산적인 방식으로도 벡터의 길이를 구할 수 있다.
벡터의 길이를 구하는 공식은 위와 같다. 벡터의 각 원소를 제곱한 뒤, 모두 더하여 제곱근을 구하면, 벡터의 길이가 나온다.
다시 [그림 1]을 보자. V1의 좌표는 (2, 2)이다. 이것을 공식에 대입하면 :
위와 같은 값이 나온다. 이것은 사실 피타고라스의 정리에서 유도된 빗변의 길이를 구하는 공식이다. 벡터는 항상 각 축을 대상으로 직각을 이루는 직각 삼각형의 형태이기 때문에 이 공식으로 길이를 구할 수 있는 것이다.
벡터의 길이는 즉, 거리로, 벡터의 뺄셈을 이용하면 두 벡터 간의 거리를 구할 수 있다.
3차원 벡터에 대한 공식은 2차원 공식에 z축 좌표를 추가해서 계산하면 된다.
벡터의 정규화(Normalize)
벡터의 정규화는 현재 벡터의 방향을 유지한 채로 벡터의 길이를 1로 만드는 것을 의미하며, 이를 단위 벡터라고 부른다.
단위 벡터를 구하려면 벡터의 각 원소를 벡터의 길이로 나누어 주면 된다. 예를 들어 [그림 1]의 V1을 단위 벡터로 만들려면 V1의 각 원소 (2, 2)를 각각 벡터의 길이인 2.828427로 나누어주면 된다. 그러면 각 원소의 값은 (0.707106..., 0.707106...)이 된다. 이렇게 나온 단위 벡터에 대해서 다시 벡터의 길이를 구해보면 1의 근사값이 나올 것이다.
이런 단위벡터는 정확히 벡터의 방향만을 추출하고자 할 때 사용되는데, 주 사용처를 이야기 해보자면, 만약 캐릭터를 마우스의 방향으로 이동시키려고 할 때, (마우스 위치) - (캐릭터 위치)로 캐릭터에서 마우스 위치 방향을 찾아낼 것이다. 그런데 이 벡터를 그대로 사용하면 마우스의 거리가 멀어지면 멀어질 수록 이 이동 벡터의 길이가 길어지기 때문에 마우스와 캐릭터의 거리가 멀면 캐릭터가 빨라지고 가까워지면 캐릭터가 느려지는 문제가 발생할 것이다.
(마우스 위치) - (캐릭터 위치)로 찾아낸 방향을 정규화해서 단위 벡터로 만든 다음에 캐릭터의 이동 속도만 곱해주면 캐릭터가 일정한 속도로 이동한다.
벡터의 내적(Dot Product)
점곱(dot product), 내적(inner product)이라고 부르는 계산으로 계산 결과 값으로 벡터가 아닌 단일 값, 즉 스칼라 값을 내는 계산이다. 때문에 스칼라 곱이라고도 부르는데, 벡터와 스칼라의 곱셈과 헷갈려서는 안된다.
계산 공식은 위와 같다. 벡터의 각 원소끼리 곱한 뒤, 모두 더하는 것으로 벡터의 내적을 구할 수 있다.
이렇게 나온 계산 결과의 의미는 내적의 값이 0이면 두 벡터의 각이 90도이고, 0보다 크면 두 벡터 사이의 각도가 90도보다 작고, 0보다 작으면 각도가 90도보다 크다는 의미이다. 여기에 삼각함수를 이용하면 두 벡터 사이의 각도를 구할 수 있다.
벡터의 외적(Cross Product)
가위곱(cross product), 외적(outer product)이라고 부르는 계산으로 두 벡터와 모두 직교하는, 즉 두 벡터와의 각이 모두 90도를 이루는 벡터를 결과값으로 내며, 3차원 공간에서만 성립하는 계산이다.
외적의 계산 공식은 위와 같다.
V1과 V2에 대해서 직교하는 벡터는 V3, V4 둘 다 될 수 있는데, 이 결과는 왼손 좌표계를 사용하느냐, 오른손 좌표계를 사용하느냐에 따라 결과가 달라진다. 왼손 좌표계에서 V2 X V1의 결과값은 V3로 나오고 오른손 좌표계에서는 V4로 나온다. 이렇게 나온 벡터를 법선 벡터(Normal Vector)라고 부른다.
그래서 벡터의 외적은 [그림 8]과 같이 한 면이 바라보는 방향을 구하는 용도로 주로 사용된다.
유니티 엔진의 벡터
그러면 이제 유니티 엔진에서의 벡터에 대해서 알아보자.
Vector2 vector2 = new Vector2();
vector2.x = 1f;
vector2.y = 1f;
Vector3 vector3 = new Vector3();
vector3.x = 1f;
vector3.y = 1f;
vector3.z = 1f;
위의 코드 예시는 유니티에서 사용되는 Vector2 구조체와 Vector3 구조체이다. Vector2 구조체는 2차원 평면 공간에 속하는 벡터로 X축의 좌표를 표시하기 위한 x 변수와, Y축의 값을 표시하기 위한 y 변수를 가진다. Vector3 클래스는 여기에 더해 Z축을 표시하는 z 변수까지 가진다.
Vector2는 대부분 UI 같은 2D 공간이나 2D 게임을 제작할 때 사용되고, Vector3는 일반적인 3D 공간에서 사용된다.
자, 그렇다면 우리는 벡터와 관련된 기능을 전부 직접 구현해서 사용해야 할까? 아니다. 유니티에서는 이러한 벡터와 관련된 기능들을 모두 제공한다.
벡터의 덧셈과 뺄셈
Vector3 v1 = new Vector3(1f, 2f, 0f);
Vector3v2 = new Vector3(2f, 1f, 0f);
// 벡터의 덧셈
Debug.Log("v1 + v2 = " + (v1 + v2));
// 벡터의 뺄셈
Debug.Log("v1 - v2 = " + (v1 - v2));
벡터의 덧셈과 뺄셈은 간단하게 일반 덧셈과 뺄셈을 하듯이 연산자를 사용하면 바로 구할 수 있다.
벡터와 스칼라의 곱셈
// 벡터와 스칼라의 곱셈
Vector3 v1 = new Vector3(1f, 1f, 0f);
int scalar = 4;
Debug.Log("v1 * scalar = " + (v1 * scalar));
벡터와 스칼라, 단일 정수 혹은 단일 실수와의 곱셈 역시 일반 계산과 같이 간단하다.
벡터의 길이
Vector3 v1 = new Vector3(2f, 2f, 0f);
// 벡터의 길이
Debug.Log("length of v1 = " + (v1.magnitude));
벡터의 길이는 Vector3 구조체에 포함되어 있는 magnitude 프로퍼티를 통해서 가져올 수 있다. 이것은 Vector2에서도 똑같다.
벡터의 정규화
Vector3 v1 = new Vector3(2f, 2f, 0f);
// 정규화된 단위 벡터
Vector3 normalizedVector = v1.normalized;
Debug.Log("||v1|| = " + normalizedVector);
// 단위 벡터의 길이 확인
Debug.Log("length of ||v1|| = " + normalizedVector.magnitude);
Vector3 구조체의 normalized 프로퍼티를 이용하면 정규화된 단위 벡터를 가져올 수 있다. magnitude 프로퍼티를 다시 사용해보면 단위 벡터의 길이가 1임을 확인할 수 있다.
벡터의 내적을 구하려면 Vector3 클래스의 정적 함수인 Dot 함수를 사용하면 된다. 벡터의 내적에 대해서 설명했듯이, v1과 v45 사이의 각도는 90도 보다 작기 때문에 0보다 큰 값이 나왔고, v1과 v90 사이 각은 정확히 90도이기 때문에 0, v1과 v135 사이 각은 90도보다 커서 0보다 작은 값이 나온 것을 확인할 수 있다.
덤으로 Vector3의 또 다른 정적 함수인 Angle 함수를 사용하면 두 벡터 사이의 각을 얻을 수 있다.
벡터의 외적
Vector3 v1 = new Vector3(2f, 0f, 0f);
Vector3 v2 = new Vector3(0f, 0f, 2f);
// 벡터의 외적
Debug.Log("v1 X v2 = " + Vector3.Cross(v1, v2));
벡터의 외적은 Vector3 클래스의 정적 함수인 Cross 함수를 통해서 구할수 있다.
이번 섹션에서는 벡터와 그 계산법을 알아보고 유니티 엔진에서는 어떻게 사용되는지 알아보았습니다.
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
언리얼 엔진에서 표준 머티리얼을 생성하고 수정하는 작업은 꽤나 시간을 많이 소모하는 작업에 속한다. 특히 머티리얼을 수정하고 실제 엔진에 적용되는 시간이 꽤나 걸린다.
수정 작업이 머티리얼의 그래프를 수정해야하는 작업이라면 감수할 수 밖에 없는 시간 소모이지만, 머티리얼 그래프에 대한 수정이 아니라 단순 수치 조정에 불과한 작업이라면 적당한 수치를 찾을 때까지 소모하는 시간이 만만치 않게될 것이다.
혹은 머티리얼 A와 머티리얼 B의 동작은 똑같지만 텍스쳐가 다르거나 러프니스 값이 달라서 반짝임 정도만 다르다고 할 때, 완전히 새로운 표준 머티리얼을 만드는 것은 분명히 시간과 노력의 낭비가 될 것임에 틀림이 없다.
이러한 시간 소모를 줄이기 위해서 언리얼 엔진에서는 표준 머티리얼에 값이나 텍스쳐 등을 바꿀 수 있는 머티리얼 파라미터(Material Parameter)와 표준 머티리얼을 상속받아 머티리얼 파라미터를 수정해서 다른 머티리얼처럼 사용할 수 있는 특수한 유형의 머티리얼인 머티리얼 인스턴스(Material Instance)를 제공한다.
이렇게 표준 머티리얼에서 바리에이션이라고 할 수 있는 머티리얼 인스턴스를 만드는 작업을 머티리얼 인스턴싱(Material Instancing)이라고 한다.
우선 파라미터와 인스턴스를 배우기 이전에 프로젝트에서 새 머티리얼을 추가하자. 머티리얼을 추가하는 방법은 콘텐츠 브라우저 패널에서 신규 추가 버튼을 누른 다음 머티리얼 항목을 선택하면 된다.
새로 추가한 머티리얼의 이름은 TestMaterial로 하자. 생성된 머티리얼을 더블클릭하면 머티리얼 에디터가 열린다.
머티리얼 파라미터(Material Parameter)
머티리얼 파라미터란 표준 머티리얼을 다시 컴파일하지 않고도 머티리얼 인스턴스에서 머티리얼을 수정할 수 있도록 해주는 특수한 머티리얼 표현식이다. 이 머티리얼 파라미터 노드는 표준 머티리얼의 머티리얼 그래프 안에서 다른 노드과 비슷하게 동작하지만, 머티리얼을 컴파일하고 머티리얼 인스턴스에서 사용할 때는 머티리얼 파라미터의 값을 실시간으로 수정하거나, 머티리얼을 새로 컴파일하지 않고도 머티리얼의 모양과 느낌을 다르게 바꿀 수 있다.
머티리얼 파라미터 생성하기
기존 머티리얼 노드를 파라미터로 변환
기존의 머티리얼 노드에 우클릭하여 파라미터로 변환을 선택하면 머티리얼 파라미터로 변환된다.
이 방법이 머티리얼 파라미터를 만드는 가장 간단한 방법이지만, 머티리얼 그래프에서 모든 노드가 머티리얼 파라미터로 변환되지는 않는다. 파라미터로 변환 메뉴는 머티리얼 파라미터로 변환이 가능한 노드에서만 표시된다.
팔레트에서 파라미터 추가하기
머티리얼 에디터의 팔레트 패널에서 Parameter를 검색하면 머티리얼 그래프에 추가할 수 있는 파라미터가 모두 나온다. 이중에 필요한 파라미터를 머티리얼 그래프에 드래그함으로써 머티리얼 파라미터를 추가할 수 있다.
우클릭 메뉴에서 파라미터 추가하기
머티리얼 그래프 빈 자리에 우클릭해서 뜨는 컨텍스트 메뉴에 Parameter를 검색해서 머티리얼 파라미터를 추가할 수 있다.
머티리얼 파라미터 이름 변경하기
머티리얼 파라미터의 이름은 매우 중요하다. 만약 C++ 코드나 블루프린트에서 머티리얼 파라미터의 값을 변경하고자 한다면 이 머티리얼 파라미터의 이름을 알고 있어야 하기 때문이다. 물론 여러개의 파라미터를 만들면 자동으로 Param, Param_1 같이 이름이 자동으로 지어지지만, 원활한 작업을 위해서는 파라미터의 이름을 명확하게 짓는것이 중요하다.
파라미터의 이름을 바꾸는 법을 배우기 전에 우선 머티리얼 그래프에 VectorParameter를 하나 추가하고 제일 위의 하얀색 소켓과 머티리얼의 베이스 컬러 소켓을 연결하자.
이 VectorParameter[각주:1]는 머티리얼의 색상을 결정하는 파라미터로 사용할 것이다. 이 파라미터의 이름은 Color가 적당할 것이다. 그럼 이 파라미터의 이름을 Color로 바꾸는 방법을 배워보자.
방법 1. 머티리얼 파라미터의 이름 클릭
첫 번째 방법은 머티리얼 파라미터를 선택한 상태에서 파라미터의 이름을 클릭하는 것이다. 그러면 아래의 이미지와 같이 파라미터의 이름을 변경할 수 있게 된다.
방법 2. 디테일 패널에서 변경
두 번째 방법은 머티리얼 파라미터를 선택한 다음, 디테일 패널에서 Parameter Name을 변경하는 것이다.
파라미터의 이름을 변경하는 방법을 배웠으니 편한 방법을 선택해서 VectorParameter의 이름을 Color로 변경한다.
그 다음엔 ScalarParameter[각주:2]를 두 개 만들고 이름을 각각 'Metallic', 'Roughness'로 정하고 메탈릭 소켓과 러프니스 소켓에 연결해주자.
머티리얼 파라미터 기본값 변경하기
표준 머티리얼에서는 머티리얼 파라미터의 기본값을 설정할 수 있다. 나중에 머티리얼 인스턴스를 처음 생성할 때, 머티리얼 파라미터의 기본값은 이것을 따르게 된다.
파라미터의 기본값은 머티리얼 파라미터 노드를 선택한 다음 디폴트 패널에서 수정할 수 있다.
표준 머티리얼에서의 Color 기본값은 {1.0, 0.5, 0.0, 0.0}으로 설정해주자.
기본값을 변경했다면, 상단의 메뉴바에서 적용 버튼을 누르고 저장 버튼을 누른 뒤, 머티리얼 에디터를 닫는다.
덤으로, 파라미터의 기본값을 변경했을 때 프리뷰에 적용되는 시간이 걸리고, 적용 버튼을 눌렀을 때 변경내용을 원본 머티리얼과 월드의 사용된 곳에 적용한다는 프로그레스바가 뜨는 것을 봤을 것이다. 지금은 머티리얼이 매우 간단하고 월드에 적용한 곳이 없어서 적용이 매우 빨랐지만, 복잡한 머티리얼이고 월드에 사용된 곳이 많았다면 이 적용되는 시간이 훨씬 길었을 것이다. 앞에서도 말했지만, 이러한 요소는 개발 시간을 소모하는 중요한 요소로 가능하다면 머티리얼 인스턴싱을 사용해서 개발 시간에 있어서 불필요하게 소모되는 시간을 줄여야 한다. 이것은 두 번 강조해도 모자람이 없는 일이다.
머티리얼 인스턴스(Material Instance)
머티리얼 인스턴스는 하나의 머티리얼을 부모로 상속받아서 그 부모 머티리얼의 구조대로 동작하되, 부모 머티리얼이 파라미터로 내어주는 부분을 수정해서 부모 머티리얼의 다양한 바리에이션을 만들어낼 수 있도록 하는 기능이다.
머티리얼 인스턴스 생성하기
머티리얼 인스턴스를 생성하기 위해서는 부모로 삼고자하는 머티리얼에 우클릭한 뒤 머티리얼 인스턴스 생성를 선택하면 된다.
머티리얼 파라미터 변경하기
머티리얼 인스턴스가 생성되고 나서 더블클릭해서 머티리얼 에디터를 열어보면 표준 머티리얼의 머티리얼 에디터와는 구성이 다른 것을 확인할 수 있다.
디테일 패널에서 부모인 TestMaterial 표준 머티리얼에서 파라미터로 공개한 파라미터들을 볼 수 있다. 각 파라미터의 앞에 있는 체크박스에 체크함으로써 해당 파라미터를 사용하고 수정할 수 있다.
Color 파라미터의 체크박스를 체크하고 값을 변경해보면 표준 머티리얼에서 값을 변경할 때와는 달리 리컴파일 없이 값을 빠르게 바꿀 수 있음을 확인할 수 있다.
콘스턴트 / 다이내믹 인스턴스
머티리얼 인스턴스 유형은 머티리얼 인스턴스 콘스턴트(Material Instance Constant), 머티리얼 인스턴스 다이내믹(Material Instance Dynamic) 두 가지가 있다.
머티리얼 인스턴스 콘스턴트(Material Instance Constant)
머티리얼 인스턴스 콘스턴트(MIC)는 실행시간 전에 한 번만 계산되는 머티리얼 인스턴스이다. 그렇기 때문에 게임플레이 도중에는 변경이 불가능하지만, 그 이상의 컴파일이 필요하지 않기 때문에 퍼포먼스 상에서의 이점이 있다.
머티리얼 인스턴스 다이내믹(Material Instance Dynamic)
머티리얼 인스턴스 다이내믹(MID)은 게임플레이 도중에 머티리얼 파라미터의 값을 계산하고 변경할 수 있는 머티리얼 인스턴스이다. 게임플레이 도중에 C++코드나 블루프린트 코드를 이용해서 머티리얼 파라미터의 값을 바꿀 수 있기 때문에, 캐릭터가 피격당했을 때 색깔이 바뀐다든지, 연속으로 발사해서 과열된 총열이 빨갛게 달아오르는 등의 연출을 사용한다든지 하는 다양한 연출을 할 수 있게 된다.
MID의 생성은 에디터가 아닌 C++ 코드나 블루프린트 그래프 내에서 이루어진다. Create Dynamic Material Instance 노드를 통해서 MID를 생성하고 Set Parameter Value 노드를 통해 파라미터들의 값을 변경할 수 있다.
머티리얼 에디터에서 Vector Parameter는 RGBA 채널을 가지는 색상 파라미터 역할을 한다. 흰색 소켓은 RGBA 모든 채널의 색상이 혼합된 색을 의미하고, 빨간 소켓은 R 채널, 초록 소켓은 G 채널, 파란 소켓은 B 채널, 회색 소켓은 A 채널을 의미한다. [본문으로]
ScalarParameter는 프로그래밍에서 1개의 float값, 즉 하나의 실수를 담을 수 있는 파라미터이다. [본문으로]
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.