컴퓨터 및 게임 관련 전공인이 아닌 문외한 일반인이 언리얼 엔진을 배우면서 정리한 내용입니다.
그날그날 배웠던 내용을 제가 나중에 보기 위해 정리한 것으로, 지금 당장 보기에 부족한 점이 아주아주 많고 추후에 수정이 될 수도 있습니다.
오탈자 및 잘못 기재된 내용 지적, 부족한 내용 설명은 언제든지 환영입니다.
본글은 언리얼 엔진 5.5.4 버전 영문판을 기준으로 합니다.
----------------------------------------------------------------------------------------------------------------
12일차 학습 내용
- Blueprint
Map Range Clamped
Delta Time
Lerp
Interp to
- 간단한 Platform 게임 제작
계단 모양 액터 배치
움직이는 발판 제작
점프패드 제작
- Random
Boolean
float / int
Rotator
Vector
Bounding
Cone
- Spline
Spline BP
Blueprint
Map Range Clamped
"Clamp" 는 일차에서 배웠듯이 일정 범위의 값을 지정해주는 역할이다.
"Clamp" 기능을 사용해보기 전에, 일단은 제한할 값을 회전으로 해줄 회전하는 오브젝트 하나를 생성하겠다.

기존에 만들어뒀던 BP에 Cube를 추가하고, "Cube Rotate" 라는 새로운 함수를 생성한다.
생성한 함수에 위에서 생성한 Cube의 get 변수를 가져오고
함수의 연결선을 "Add Relative Rotation" 과 "Add World Rotation" 를 각각 연결해준다.
"Add Relative Rotation" 은 해당 오브젝트를 기준으로 하여 회전을 추가해주는 역할이고, "Add World Rotation" 해당 오브젝트가 배치된 월드를 기준으로 하여 회전을 추가해주는 역할이다.
여기서는 "Add World Rotation" 로 연결해야 정상적으로 회전이 가능하다.

그리고 "Event Tick" 에 위에서 만든 "Cube Rotation" 함수를 연결해줄 경우, Cube가 매 틱마다 1도씩 계속 회전하게 된다.
이제 "Map Range Clamped" 를 사용해보도록 하겠다.

BP를 위 그림과 같이 작성해준다.
"Map Range Clamped" 는 'Value' 가 들어오면 'In Range' 에서 정해진 값 범위 내로만 입력이 되게 하고, 'Out Range' 에서 정해진 값 범위 내로만 출력이 되게 하는 것이다.
즉, 위 BP의 "Map Range Clamped" 노드는 '-500~500' 범위의 값까지만 인식하고, 그에 따라 '-90~90' 범위의 값까지 출력한다는 의미이다.
위 함수를 해석해보자면 아래와 같다.
"현재 레벨에 배치된 액터와 컨트롤 중인 캐릭터와의 y축 거리 차이를 '-500~500' 범위 내로만 인식하고, 그에 따라 해당 액터의 x축 회전 각도를 '-90~90' 범위 내로 회전시킨다." 는 의미이다.
노드 몇 개를 추가해보도록 하겠다.

"Rendering" 의 "Visible" 의 체크를 해제하여 큐브를 비가시 상태로 만든다.

"isShowCube" 라는 'bool' 타입의 변수를 하나 생성한 뒤 눈을 켜주고, "isShowCube" 의 set 변수를 생성한 다음 'isShowCube' 를 체크해준다.
그리고 "E-Time" 의 'Map Range Clamped' 와 "isShowCube" 의 set 변수를 연결해준다.

함수 "Cube Rotate" 로 돌아가 "isShowCube" 의 get 변수를 생성하고, 위 그림과 같이 노드를 연결해준다.
위 함수에서 추가된 부분을 해석해보자면 ""isShowCube" 가 True일 경우 Cube를 가시 상태로 바꾸고 Cube에 아래 함수만큼 회전을 준다." 라는 의미이다.
Delta Time
"Delta Time" 은 1 프레임 만큼의 시간을 뜻한다.
"Delta Time" 만큼의 시간을 나타내는 법은 아래와 같다.

"Event Tick" 아래의 'Delta Seconds' 의 핀을 바깥으로 끌어서 변수로 승격시켜준다.
그러면 옆에 set 변수가 생성되며 자동으로 연결이 된다.

옆의 'Variables' 탭에서 "Delta Seconds" 의 get 변수를 생성하여 "Print String" 노드에 연결해주면 된다.

위 사진을 보면 '0.008333' 이라는 숫자가 나오는데, 이 숫자가 "Delta Time" 을 의미한다.
Lerp
8일차 마테리얼에서 사용했던 "Lerp" 와 원리는 똑같다.
입력한 a와 b 사잇값을 왔다갔다하는 것이다.

BP 상에서 'lerp' 를 검색하면 다양한 종류의 lerp가 뜬다.
앞에 있는 대문자에 따라 용도가 달라지는데, 여기서 필요한 것은 Vector 값이 들어간 'Vlerp' 이다.

우선 "Add Timeline" 으로 타임라인을 하나 생성해주고 'Float Track' 형식으로 1초의 길이로 추가해준 뒤, 각각 0초에 0, 0.5초에 1, 1초에 0의 값으로 키를 총 3개 찍어준다.

그리고 위 그림처럼 노드들을 연결해주면 된다.
"Set World Location" 노드는 입력된 값으로 'target' 의 위치를 변경시키는 노드이다.
위 BP를 해석해보면, "Cube를 가시 상태로 바꾸고, 액터의 현재 위치와 현재 위치에서 z축 +100 만큼의 위치 사이를 0.2 배속으로 왔다갔다하게 한다." 라는 의미이다.
위와 같이 위치값을 직접 입력하여 "Lerp" 를 적용시킬 수도 있고, 다른 방법으로는 "Arrow" 액터를 이용한 방법도 있다.

"Viewport" 로 들어가 "Arrow" 액터 2개를 위 그림과 같이 사이를 벌리고, 각 "Arrow" 를 구분하기 위해 색상을 다르게 생성해준다.

그 다음 "Lerp" 에 각 "Arrow" 의 위치값을 주면 된다.

마지막으로 레벨로 돌아가 두 "Arrow" 의 위치를 원하는 곳에 배치해주고, 지정한 두 "Arrow" 사이를 "Lerp" 시킬 수 있다.
"Arrow" 는 게임 시작 시 자동으로 비가시 상태가 되기 때문에 따로 설정해줄 필요가 없다.
Interp to
"Interp to" 는 범프 구간을 줌으로써 딜레이가 생겨 움직임을 조금 부드럽게 만들어주는 역할을 한다.
"Interp to" 가 적용된 플레이어를 따라다니는 구를 생성해보도록 하겠다.

우선 플레이어를 따라다닐 새로운 Sphere를 생성해준 뒤, "Rendering" 의 "Visible" 의 체크를 해제하여 구를 비가시 상태로 만든다.

새로 만든 Sphere의 충돌 설정을 위 그림처럼 'BlockAllDynamic' 에서 'NoCollision' 으로 수정해준다.
따라다닐 구체의 물리적 충돌 판정을 없애기 위함이다.


그리고 위 그림처럼 BP를 작성해주면 된다.
구를 가시 상태로 만든 뒤 캐릭터의 위치에서 생성하여 따라다니게 명령하는 것이다.
"Event Tick" 에 연결하지 않으면 생성된 구체가 캐릭터를 따라다니지 않고, 충돌 범위 내로 들어갈 때마다 플레이어가 있는 위치에 생성되는 것만을 반복한다.

위 그림처럼 z축 벡터값을 추가하면 캐릭터 머리 위에서 지속적으로 따라다니게 된다.

'interp' 를 검색 시 "Lerp" 와 비슷하게 앞에 알파벳이 붙어있는데, 이 또한 상호작용하는 역할이 각자 다르다.
* V: vector, F: float, T: transform, R: rotation
여기서는 구체의 위치를 변경시킬 벡터값이 필요하므로 "VInterp To" 를 불러온다.

"VInterp To" 노드를 생성하여 위 그림과 같이 연결해주고, 'Interp Speed' 에 적당한 수치를 입력 시 캐릭터와 시간차를 두고 부드럽게 따라오게 된다.
'Interp Speed' 에 입력한 숫자가 클수록 쫓아오는 딜레이가 줄어든다.
간단한 Platform 게임 제작
계단 모양 액터 배치

계단 모양의 액터는 "Place Actor" 가 아닌 "Modeling" 으로 들어가면 볼 수 있다.

계단 모양의 액터를 레벨에 배치하면 수정이 가능한데, "Shape" 에서 계단의 형식, 계단 수, 계단 너비, 계단 높이 등 다양하게 수정이 가능하다.

계단의 모양을 최종적으로 정했을 경우, 아래의 'Accept' 를 눌러 확정지어 레벨에 완전히 배치할 수 있다.
움직이는 발판 제작
움직이는 발판으로 사용할 BP 액터를 생성해준다.

발판으로 쓸 하나의 오브젝트를 생성해주고 , 해당 오브젝트의 하위 항목으로 "Box Collision" 이 들어가도록 설정해준다.
그림에는 없지만 위 "Lerp" 에서 한 것과 같이 "Arrow" 를 이용하여 Lerp 할 것이기에 "Arrow" 2개를 생성하여 양 옆으로 배치해준다.


위 그림과 같이 BP를 작성해주고 타임라인 또한 위와 같이 해준다.

게임이 시작되면 레벨에 배치한 모든 발판이 "New Rate" 에서 설정한 속도대로 발판이 지정된 두 "Arrow" 사이를 반복하여 움직이는 명령이다.


위 두 사진처럼 노드 연결을 바꿔준다.
BP에서 "Event Begin Play" 노드 대신 위 BP를 하나의 Custom Event로 바꿔주고 바로 위 그림처럼 충돌 이벤트에 연결해주면, 레벨에 배치한 모든 발판이 캐릭터가 발판에 올라탄 순간부터 움직이기 시작하고 발판 별로 설정한 'New Rate' 의 수치의 속도로 각자 움직인다.

"Event Begin Play" 에 "If" 노드를 추가하여 조금 수정해주었다.
"isAuto" 라는 새로운 Bool 변수로, 플레이어와의 충돌을 인식했을 때 움직일 것들과 미리 움직일 것들 구분해서 적용한 것이다.
"isAuto" 값이 True 일 경우 자동으로 움직이고, False 일 경우 플레이어가 발판에 올라간 뒤에 움직인다.

그리고 위 그림처럼 충돌 범위를 벗어나는 이벤트를 추가하여, 모든 발판이 해당 발판을 벗어나면 멈추는 기능도 만들어줄 수 있다.

TL에서 'Loop' 를 끄고, Bool 형의 "Looping" get 변수 추가하는 식으로 loop 설정이 가능하다.
이렇게 하면 발판 별로 loop 설정이 가능하다.

위 사진처럼 충돌 이벤트 발생 시 소리 재생을 추가해줄 수도 있다.
다만 여기서 오류가 발생하는데, 소리 출력 설정 시 'isAuto' 가 'off'로 설정된 것들만 소리가 나게된다.
그 이유는 위 If문에서 'isAuto' 를 켜둔 것들에 'No Collision' 으로 설정해뒀기 때문에, 충돌 이벤트를 인식하지 못해 소리가 나지 않게된다.
의도하지 않은 설정이므로 "Set Collision" 노드를 제거하고 수정하여 발판 별로 플레이어를 인식 후 이동하는 것을 설정해주도록 하겠다.

수정은 위 그림처럼 충돌 이벤트 발생 시에 If 노드를 추가하여, 'isAuto' 값이 False 일 경우 플레이어가 발판에 올라간 뒤에 움직이는 노드를 추가해주면 된다.

위 그림과 같이 BP를 작성해주면 충돌 범위를 벗어나는 이벤트 발생 시 'isAuto' 를 'off' 설정한 발판들, 즉 플레이어를 인식 후 이동하는 발판들만 그 자리에서 바로 멈추게 된다.
그리고 loop를 실행하는 노드를 번거롭게 "Event Begin Play" 에서 추가하는게 아닌, 타임라인에 연결하여 설정해줄 수도 있다.

위에서 만든 타임라인을 열어 Float Track 을 2개 추가해준다.
그리고 각각 출력값이 '0' 과 '1' 인 두 키 사이에 키를 Track 별로 하나씩 추가해준다.
이렇게 하면 각각 이동범위의 끝자락에 갔을 때 잠시 멈춰있게 된다.

그리고 타임라인에 새로 만든 위의 트랙들을 If 노드와 연결해주고 위에서 만든 Bool 형 'Loop' 변수를 위 그림과 같이 연결해주면, 'isLooping' 이 'off' 인 발판들은 자동으로 움직이는게 아닌 플레이어가 발판에 올라갔을 때 움직이게 된다.

위 사진처럼 소리 출력 후에 "Delay" 노드를 넣어주면 소리가 여러번 출력되는 오류를 사전에 방지할 수 있다.
점프패드 제작

위 그림의 "Launch Character" 노드는 캐릭터를 강제로 적혀있는 값의 속도로 이동시키는 노드이다.
노드 아래의 'Override' 는 해당 캐릭터의 현재 위치값에 해당 값을 추가한다는 의미이다.
즉, 점프 상태로 발판에 진입 시, 들어온 점프 상태의 좌표 값에 해당 속도 값을 추가한다는 의미이다.
Random
각 자료형에 무작위의 값을 부여해주는 것이다.
각 자료형에 대한 정의는 2일차에 나와있으니 생략하도록 하고, BP 및 노드의 해석만 하도록 하겠다.
Boolean

"Select Color" 노드는 입력된 값이 True면 a, False면 b의 색상을 노출시키는 노드이다.
아래에 있는 "Random Bool with Weight" 노드는 가중치를 부여해주는 노드이다.
위 그림처럼 연결해주면 a의 색이 발현될 확률을 80%로 올려준다는 것이다.
위 그림과 같이 노드를 작성해주고 실행하게 되면, 레벨 상에 배치한 Cube의 색상이 80% 확률로 빨간색으로 나오고, 나머지 20% 확률로 파란색으로 나오게 된다.
float / int

위 그림과 같이 노드를 작성해주고 실행하게 되면, 레벨 상에 배치한 Cube가 0.1초마다 무작위로 부여받은 z축의 위치값만큼 순간이동하게 된다.
다만 부여된 float의 값이 0~1 이기에 아주 미세하게 움직이게 된다.
아주 미세하게 움직이는 걸 가시화 시키기 위해 벡터값을 좀 더 키워주도록 하겠다.

우선 "Random Float" 노드에 곱셈 노드를 연결해주고, 숫자를 입력해주는 부위를 우클릭 하여 'To Vector' 로 바꿔준다.

그러면 위 그림과 같이 수치를 입력할 수 있었던 공간이 벡터를 입력할 수 있는 곳으로 바뀌고, 출력값도 벡터값으로 바뀌게 된다.
x, y, z축으로 split 해줬던 핀을 다시 합쳐 벡터값으로 만들어준 뒤, 곱셈의 z값에 100을 넣어주면 부여되는 "Random Float" 값이 100배가 되어 움직임이 좀 더 잘 띄게 된다.

움직임을 더 극대화하고 싶을 경우, "Random Float" 노드가 아닌 "Random Float in Range" 노드를 생성하여 최솟값과 최댓값을 각각 부여해주면 된다.
int 또한 float와 같은 수치를 나타내는 자료형이기에 위 방법과 똑같이 적용할 수 있어, 생략하도록 하겠다.

Rotator

위 그림과 같이 노드를 작성해주고 실행하게 되면, 레벨 상에 배치한 Cube가 1초마다 무작위로 회전축을 지정한 뒤 임의의 값만큼 회전하게 된다.
"Random Rotator" 노드 안에 있는 'Roll' 은 체크함으로써 'Roll' (x축 회전) 을 줄 수 있는데, 무작위로 회전축을 정해주기에 생각보다 체감이 되지는 않는다.

"Lerp" 를 추가해서 무작위 회전값을 줄 수도 있다.
이 때는 회전값을 주는 것이기에 "Rlerp" 를 사용해야한다.
그리고 "Lerp (Rotator)" 노드 하단에 'Shortest Path' 라는게 있는데, 이는 회전 움직임을 최소화 해주는 것이다.
1º에서 355º로 회전을 부여했을 때, 컴퓨터는 1º에서 355º로 회전하기에 회전 움직임이 쓸데없이 크게 적용된다.
'Shortest Path' 를 체크하게 되면 그대로 1º에서 355º로 회전하는게 아닌, 1º에서 반대로 5º만큼 이동하여 355º의 값을 부여하게 된다.
그리고 이 'Shortest Path' 를 추가하기 위해서는 "Get World Rotation" 노드가 있어야한다.
여담으로 위와 같이 BP를 작성했을 경우, 'Random Rot' set 변수에 복잡하게 노드를 이어줄 필요 없이 "Random Rotator" 노드만 연결해줘도 되긴한다.
"Event Tick" 노드에 연결돼있는 "Get World Rotation" 노드에 자체적으로 회전값이 있기 때문이다.
Vector

위 그림과 같이 노드를 작성해주고 실행하게 되면, 레벨 상에 배치한 Cube에서 0.2초마다 무작위의 방향으로 0.2배 크기의 공을 발사한다.
"Random Unit Vecto" 노드는 무작위의 방향을 액터에게 부여해주는 노드이고, 방향만 부여해주기에 공이 날아갈 힘을 부여해주는 노드인 "Add Force" 를 연결해줘야한다.
* "Spawn Actor from Class" 노드에 넣는 BP 액터는 반드시 'Simulate Physics' 가 체크돼있어야 정상적으로 날아감
* 레벨에 배치된 BP 자체에서 BP 액터가 생성되기에, 레벨에 배치된 BP 액터의 큐브 위치를 조금 아래로 조정해줘야함
Bounding
"Bounding" 은 객체의 경계를 정의하는 영역을 가리키는 말이다.
여기서는 "Bounding" 내에서 무작위로 생성되는 코인을 캐릭터가 접근해서 먹게되는 BP를 작성해보도록 하겠다.

우선은 코인 BP를 생성해야한다.
자신이 원하는 대로 코인의 모형을 생성한 뒤, "Collision" 의 "Collision Preset" 을 'BlockAllDynamic' 에서 'OverlapAll' 로 바꿔줘야한다.
그래야만 플레이어가 무작위로 생성되는 코인 사이에 끼지 않게 된다.
그리고 코인에 'Sphere Collision' 과 'Cylinder Collision' 을 추가해줘야한다.
'Sphere Collision' 은 코인이 캐릭터를 인식해서 캐릭터로 들어가게하기 위함이고, 'Cylinder Collision' 은 코인이 캐릭터와 겹친 뒤 레벨 상에서 파괴하기 위함이다.

위 그림과 같이 노드를 작성해주고 실행하게 되면, 레벨 상에 배치한 Cube를 중심으로 생성된 "Random Point in Bounding Box" 의 크기 내에세 무작위의 위치에 위에서 만든 코인이 생성되게 된다.
"Random Point in Bounding Box" 의 크기는 노드의 입력한 값의 2배 크기인데, 노드에 적은 크기는 노드에 적혀있는대로 'Half Size' 이기 때문이다.
즉, 위 사진 같은 경우는 (600, 600, 40) 사이즈의 Box가 생성되는 것이다.
범위 내에서 코인이 생성되도록 만들었으니, 이제는 코인을 습득하고 파괴하는 BP를 작성해야한다.

위 그림과 같이 노드를 작성해주고 실행하게 되면, 코인이 플레이어를 인식하게 되면 플레이어에게 접근하고 플레이어와 완전히 겹치게 되면 소리를 내면서 액터가 소멸하게 된다.
"Vinterp to" 를 넣어 코인이 플레이어에게 다가가는 움직임을 부드럽게 만들어줬고, 코인이 움직이는 것이기에 벡터값이 들어간 "Vinterp to" 노드를 사용해야한다.
그리고 "Destroy Actor" 노드 후에 "Play Sound" 노드를 배치해도 소리가 나는 경우가 있으나, 액터가 사라진 다음 소리를 출력하는 명령이라 소리가 드문드문 안 날 수도 있다.
그렇기에 "Play Sound" 노드가 먼저 오고 "Destroy Actor" 가 나중에 오도록 하는 것이 바람직하다.
Cone

위 그림과 같이 노드를 작성해주고 실행하게 되면, 레벨 상에 배치한 Cube에서 0.2초마다 지정해준 원뿔형의 범위 안에서 무작위의 방향으로 0.5배 크기의 공을 발사한다.
"Random Unit Vector in Cone in Degrees" 는 "Random Point in Bounding Box" 처럼 일정 범위를 지정해주는 것이다.
'Cone Dir' 에 입력된 벡터의 방향으로 'Cone Half Angle in Degrees' 에 입력된 확산각 크기의 원뿔 범위를 생성하는 것이다.
Spline
"Spline" 은 곡선을 따라 경로를 정의하는 시스템이다.
주로 오브젝트 배치나 길을 만들 때 사용된다.
Spline BP

Spline의 BP 구조는 위 사진과 같다.
Spline은 'Construction Script' 에서만 BP를 작성한다.
Spine을 통해 오브젝트를 배치할 시에 처음부터 배치하기
회전값은 spline의 방향을 따라서 각도를 틀어주기 위함

Spline의 구조는 위 사진처럼 단순한 흰색 선으로 되어있다.
레벨 상에서 Spline을 배치한 뒤에, Spline의 흰색 선을 잡고 드래그 하면 늘어나고, alt를 누른 채로 드래그하면 점이 찍히면서 늘어난다.

"details" 탭에서 'Spline' 의 'Closed Loop' 을 체크하면 Spline의 처음과 끝점이 자연스럽게 연결되어 닫힌 도형을 만들 수 있다.
그리고 Spline에 배치된 Static Mesh는 레벨 상에서도 다른 것으로 수정이 가능하다.

'Unreal Engine > GCC Class (5.5.4)' 카테고리의 다른 글
| Unreal Engine 5 배워보기 - 14일차 (0) | 2025.04.04 |
|---|---|
| Unreal Engine 5 배워보기 - 13일차 (0) | 2025.04.03 |
| Unreal Engine 5 배워보기 - 11일차 (1) | 2025.04.01 |
| Unreal Engine 5 배워보기 - 10일차 (0) | 2025.03.31 |
| Unreal Engine 5 배워보기 - 9일차 (0) | 2025.03.28 |