본문 바로가기

언리얼엔진

13. 프리뷰 애셋 / 소켓 / 캐릭터에 무기 생성 / For Each Loop

Tip!

- Ctrl + P : 원하는 애셋 검색해서 열 수 있음

- 트랜스폼 Scale 옆 자물쇠는 전체 스케일을 모두 같은 비율에 맞춰 조정됨

 

언리얼에서는 자동으로 가비지 컬렉션을 해준다.

따라서 특정 주소를 참조하고 있는 포인터가 없다면 자동으로 가비지 컬렉션(GC)이 된다.


프리뷰 애셋 주의 사항

SkeletalMesh에서 hand_r_weapon 소켓을 추가해 주었다. 이 소켓에서 프리뷰 애셋 추가를 통해서 Sword를 바로 볼 수

있었는데, 이 프리뷰 메시를 사용할 때에 주의사항이 있다.

 

- 개체 자체의 스케일의 변화는 반영되지 않는다.

SkeletalMesh에서 프리뷰 애셋으로 SK_Sword를 추가해주었다. 그러고 나서 SK_Sword 블루프린트에서 트랜스폼

스케일의 값을 바꿔줬다면, 그 스케일에 맞춰서 hand_r_weapon 소켓의 위치를 다시 바꿔주어야 할 것이다.

하지만 SkeletalMesh에선 SK_Sword의 바뀐 스케일 값을 반영하지 못한다.

 

- 무기의 Root Component는 Mesh Component로 하는 것이 좋다

기존의 SkeletalMesh를 Root로 사용했을 때는 중점이 손잡이에 잡혀있었다.

하지만 Capsule Component를 Root로써 사용하게된다면, Weapon 블루프린트 내에서 Sword와 Capsule의 위치를

잡아주었다 해도 정작 소켓에 프리뷰로 가져다 쓰면 Root를 기준으로 써지기 때문에 Capsule의 중점으로 잡혀서 나오는 것을 볼 수 있을 것이다. 그래서 SkeletalMesh 또는 StaticMesh를 Root Component로 사용하게 되는 것이다.

 

※ 무기들을 가져다 사용할 때, 중점이 무기의 손잡이에 있는지 확인해야 한다.


개체 자체(SK_Sword)의 스케일을 바꿨거나 무기의 Root Component가 Mesh가 아닐 때, 실제로 소켓 위치에

붙여서 위치를 조정해 줄 방법이 있다.

 

우선 붙여주려는 대상의 Root Component는 Mesh로 되어있어야 가능하다.

예시를 들기위해 블루프린트 클래스 - Pawn을 하나 만들었다.

블루프린트 클래스 Pawn 설정

 

그리고 현재 레벨에 각각 예시로 만든 Pawn과 Sword를 올려준다.

레벨에 Pawn과 Sword를 올려둔 모습

 

이제 Sword를 선택 후, 우클릭 - 붙히기를 보면 우리가 올린 Pawn을 선택해준다.

Sword 선택 후, 우클릭 - 붙히기 - 예시로 만든 Pawn(여기선 Sample)

 

그러면 해당 Pawn의 SkeletalMesh에 있는 본 또는 소켓 중 어디에 붙힐 것인지 선택할 수 있다.

여기서 우리가 만들었던 hand_r_weapon 소켓을 선택해주면, 그 위치를 중심으로 잡게 된다.

hand_r_weapon 소켓 선택

 

하지만 Sword의 World기준 트랜스폼이 유지된 채로 붙혀져있는 상태이므로, 위치와 회전값을 모두 초기화시켜주면

바로 Pawn의 hand_r_weapon 소켓 위치와 회전값에 맞게 되는 것을 볼 수 있다.

Sword 트랜스폼 초기화를 통해 소켓의 트랜스폼 값만 남는다.

 

이제 여기서 Sword를 적절한 위치로 이동시켜준 뒤, Sword의 트랜스폼 값을 hand_r_sword 소켓 트랜스폼에 더해준다면

소켓이 해당하는 트랜스폼에 위치하게 되는 것이다.


캐릭터에 무기 생성해주기

이제 실행 시 우리가 만들었던 Sword를 캐릭터에게 생성해주기 위한 작업을 할 것이다.

캐릭터와 적을 만들 것인데, 둘 다 Weapon은 가지고 있을 것이기 때문에, 캐릭터와 적이 상속하는 BP_Character에서

추가해줄 것이다.

 

우선 변수 추가(WeaponClasses)로 만든 뒤, 변수 타입을 BP Weapon으로 바꿔줄 것이다.

Weapon을 검색하여 BP Weapon을 선택하고 클래스 레퍼런스로 변수 타입을 만들어주었다.

그리고 변수 유형을 배열로 바꿔준다.

WeaponClasses 변수 생성

 

※ 변수 타입 : 클래스 레퍼런스

어떤 형식, 유형 자체를 데이터로 저장이 가능하다.(메타데이터 : 데이터를 설명하는 데이터)

즉, BP_Weapon 클래스의 변수 WeaponClasses에는 BP_Weapon과 그 자식 클래스들만 가질 수 있다.

BP_Weapon 상속구조에 포함된 대상만 가능한 것이다.

선택 가능한 원소 유형은 2가지만 나오는 것을 볼 수 있다.

 

여기서 BP_Weapon은 구체화 된 것이 아닌 추상 클래스 역할을 할 뿐이다.

따라서 BP_Weapon의 클래스 세팅에서 클래스 옵션의 Generate Abstract Class를 체크해주어 추상화 시킨다.

BP_Weapon의 클래스 세팅에서 체크

 

이렇게 설정해주면 WeaponClasses 변수의 선택가능한 원소 유형 중에 BP_Weapon이 사라져 있는 것을 볼 수 있다.

이제 컴파일 후에  BP_Player의 클래스 디폴트에서 Weapon Classes 배열을 추가할 수 있게 바뀌었다.

여기서 원소 하나를 추가하고 BP_Sword로 설정해준다.

BP_Player의 클래스 디폴트에 생긴 Weapon Classes


이제 플레이 시 무기 생성이 되서 가지고 있도록 하기 위해 BP_Character의 이벤트그래프로 돌아온다.

아까 만들었던 WeaponClasses 변수를 Getter 노드로 추가해준다.

 

WeaponClasses 배열에는 어떤 클래스인지 원소 하나하나가 들어있고, 해당 원소의 무기들을 전부 생성해줄 것이다.

때문에 배열의 원소 갯수만큼 반복시켜주기 위해서 For Each Loop 노드를 사용해준다.

For Each Loop는 알아서 배열의 크기만큼 돌아가는 범위기반 For문이다.


For Each Loop 노드

For Each Loop 노드

- Loop body : 매 반복 회차마자 들어오는 실행 핀

- Completed : 반복 다 끝나고 나가는 실행 핀

 

Array로 들어간 값이 Array Element로 나갈 때, 복사된 값으로 나가므로 값 변경을 해도 원본은 바뀌지 않는다.


이렇게 For Each Loop로 원소의 갯수만큼 반복시켜서 배열에 있는 모든 무기들을 생성해 줄 것이다.

따라서 Spawn Acter from Class노드를 추가해준다.

 

Spawn Acter from Class 노드

Spawn Acter from Class 노드

- Spawn Transform : 어떤 위치, 크기, 회전값으로 생성될지 정함

                                    직접 트랜스폼과 연결 / MakeTransform 노드를 연결 / 매크로 생성하여 연결 / 구조체 핀 분할 가능

 

- Collision Handling Override : 스폰 시 해당 위치에 무엇인가 있을 때에 어떻게 행동할지 결정

                   -- Do Not Spawn : 생성하지 말 것

                   -- Try To Adjust Location, Don't Spawn If Still Colliding : 스폰위치 조정해보고 안되면 생성하지 말 것

                   -- Try To Adjust Location, But Always Spawn : 스폰위치를 조정하여 무조건 생성할 것

                   -- Always Spawn, Ignore Collisions : 무조건 생성할 것(충돌 무시)

                   -- Default : 언제나 그 위치에 생성할 것 / Always Spawn, Ignore Collisions과 비슷함

 

- Owner : 스폰된 대상의 소유자(자기 자신 self 노드를 연결함)

 

- Instigator : 최종 소유자 / Owner와 비슷한 느낌이지만 다를 수 있음 ex) Player > Bow > Arrow

                      별도로 지정하지 않으면 Owner를 따라감

 

- Return Value : 주소(레퍼런스)를 넘겨줌. 따라서 이걸 저장해줄 곳이 필요함.


Spawn Actor를 통해 생성하는 Weapon들은 동적할당이라고 보면 된다. C++에서 new를 통해 동적할당하는 것과

비슷한데, 이제 이 레퍼런스 값을 담아놓을 곳이 필요하다.

 

이제 Spawn Actor의 Return Value를 변수로 승격하여 Weapons 변수로 만들어 준다.

그런데 Spawn Actor로 만들어지는 무기들이 여러개이기 때문에 Weapons변수 또한 배열로 바꿔준다.

 

Weapons 변수를 Getter 노드로 추가해준 뒤, 이제 Weapons에 스폰된 무기들을 넣어주기 위해 ADD를 사용하게 된다.

변수로 승격하여 만든 배열 Weapons / ADD를 통해 Weapons에 생성된 무기 저장


노드 추가 시에 ADD를 검색했을 때, ADD와 ADD Unique 두개가 보일 것이다.

ADD와 ADD Unique

- ADD : 일단 생성한다.

- ADD Unique : 같은 중복되는 값이 있다면 생성하지 않는다. 하지만 여기서 받는 값은 주소값이므로 만약 같은 검이

                         두개라 할지라도 서로 다른 주소값으로 인해 중복 검사가 되지 않는다.

 

따라서 여기선 어짜피 되지않는 중복검사이므로 그냥 ADD를 사용하게 된다.


여기까지 설정한 후, 실행해보면 캐릭터와 무기가 있는 것을 볼 수 있는데 무기의 위치 원점에 생성된 것을 볼 수 있다.

따라서 이후에 무기의 위치를 손 또는 등에 위치하도록 바꿔보도록 할 것이다.

설정 후, 플레이 화면