https://awesometuts.com/blog/unreal-engine-side-scroller-cpp-2/
이 자습서 시리즈의 1부 에서는 RunnerCharacter C++ 클래스를 만들고 플레이어 액터의 이동 동작을 만들었습니다.
또한 RunnerCharacter 클래스에서 BP_RunnerCharacter 블루프린트를 생성했고 기본 폰 클래스를 BP_RunnerCharacter로 설정할 수 있는 게임 모드 블루프린트를 생성했습니다.
이 파트에서는 Spike 및 BaseLevel 클래스를 생성하고 이를 사용하여 게임의 장애물 및 수평 부분을 생성합니다.
스파이크 클래스 만들기
C++ Classes-> SideRunner 폴더에서 오른쪽 클릭 -> New C++ Class. 팝업 창에서 액터를 부모 클래스로 선택하고 다음을 클릭합니다:
새 클래스의 이름을 Spike로 지정하고 클래스 만들기 버튼을 클릭합니다.
우리는 이 클래스를 사용하여 게임에 스파이크 장애물을 생성할 것입니다. 청사진으로도 이 작업을 수행할 수 있지만 이 튜토리얼에서는 C++에 중점을 두기 때문에 클래스를 사용하겠습니다.
새 C++ 클래스를 만들 때마다 Visual Studio에서 프로젝트를 다시 로드하라는 메시지가 표시됩니다. 파일 수정 창에서 모두 다시 로드 단추를 누르기만 하면 됩니다.
이렇게 하면 만든 새 클래스가 Visual Studio에서 프로젝트 구조의 소스 폴더에 나타납니다.
스파이크 장애물 블루프린트 생성
이제 스파이크 장애물에 대한 클래스가 있으므로 여기에서 청사진을 만들 수 있습니다. Content -> Blueprints 폴더에서 우클릭 -> New Folder를 클릭하고 새 폴더 이름을 Obstacles로 지정합니다.
Obstacles 폴더 안에 청사진을 만들고 이름을 BP_Spike로 지정하고 방금 만든 Spike 클래스를 상속하는지 확인합니다.
에디터에서 BP_Spike 블루프린트를 열고 Components 탭에서 Add Component 버튼을 클릭하고 스태틱 메시를 검색합니다. Static Mesh 구성 요소의 이름을 Spike로 변경하고 Static Mesh 설정의 세부 정보 탭에서 드롭다운 목록을 클릭하고 Shape_QuadPyramid 모델을 필터링하여 선택합니다.
정적 메시 설정 아래에 있는 재료 설정에서 드롭다운 목록을 클릭하고 M_Brick_Clay_New 재료를 필터링하여 피라미드 모델에 적용합니다.
디테일 Transform 설정에서 위치 속성의 Z 값을 -50으로 설정합니다.
컴파일 및 저장을 누르는 것을 잊지 마십시오. 이것이 우리가 완료했을 때의 스파이크 모습입니다.
커스텀 콜리전 프리셋 만들기
충돌 사전 설정은 액터가 다른 액터와 충돌하는 방식 또는 전혀 충돌하지 않는 방식을 정의합니다.
충돌 사전 설정이 무엇인지 모르는 경우 여기 를 클릭하여 이에 대해 알아볼 수 있습니다 .
이제 선택할 수 있는 기본 충돌 사전 설정이 있지만 사용자 정의 충돌 사전 설정을 사용하고 생성한 사용자 정의 오브젝트 채널과 결합할 수도 있습니다.
이를 위해서는 편집 -> 프로젝트 설정에서 프로젝트 설정을 열고 엔진 카테고리 아래에 있는 충돌 탭을 클릭해야 합니다.
개체 채널에서 새 개체 채널 버튼을 클릭합니다.
새 채널 창에서 채널 이름을 Spike로, Default Response를 Overlap으로 설정합니다.
Overlap Default Response는 무엇을 합니까?
Overlap Default Response는 비고체 몸체처럼 작동하여 플레이어 액터가 통과할 수 있도록 하지만 플레이어가 스파이크 장애물에 닿는 즉시 플레이어를 죽이기 때문에 알아차리지 못할 것입니다.
액터 및 커스텀 오브젝트 채널
에디터에서 BP_Spike 블루프린트를 열고 Components 창에서 Spike Static Mesh 컴포넌트를 선택한 다음 Details 탭에서 Collision 설정을 찾습니다.
Collision Presets의 드롭다운 목록을 클릭하고 목록에서 Custom을 선택합니다.
Collision Enabled 목록에 대해 Query Only(No Physics Collision)를 선택하고 Object Type 목록에 대해 Spike를 선택합니다.
Collision Enabled 옵션을 사용하면 액터가 충돌할 수 있는지 여부를 지정하고 다른 액터와 충돌을 등록할 수 있습니다.
Spike 장애물의 경우 충돌만 등록하고 물리적 충돌이 발생하지 않도록 지정했습니다. 예를 들어 Spike는 솔리드 바디로 계산되지 않습니다.
충돌 응답의 경우 무시를 설정할 카메라를 제외한 모든 것을 스파이크가 겹치게 만들 것입니다.
이렇게 하면 카메라 액터와의 충돌을 무시하므로 카메라를 제외하고 지정된 충돌 사전 설정을 사용하는 블루프린트와 스파이크 블루프린트가 겹칩니다.
BP_Spike에 대한 변경 사항이 청사진에 적용되도록 컴파일 및 저장을 누르는 것을 잊지 마십시오.
기본 수준 클래스
다음 단계는 절차적 레벨 생성이라는 방법을 사용하여 스폰될 레벨 파트를 만드는 것입니다.
새 클래스를 만드는 것으로 시작하겠습니다. C++ 클래스 -> SideRunner 폴더에서 마우스 오른쪽 버튼을 클릭 -> 새 C++ 클래스를 클릭합니다.
액터를 상위 클래스로 선택하고 다음을 클릭합니다.
다음 창에서 클래스 이름을 BaseLevel로 지정하고 클래스 만들기 버튼을 클릭합니다.
Visual Studio에서 BaseLevel.h 파일을 열고 상단, 클래스 선언 위와 마지막 #include 문 아래에 다음 줄을 추가합니다.
class UBoxComponent;
이 자습서 시리즈의 이전 부분 에서 전방 선언에 대해 이야기했습니다 . 정방향 선언의 경우 특정 유형의 변수를 선언할 때마다 이를 수행할 필요가 없습니다. 대신 파일 시작 부분(예: 마지막 #include 줄 아래)에서 클래스 유형을 정방향 선언할 수 있습니다. 전체 클래스에서 해당 변수 유형의 모든 선언에 대해 충분해야 합니다.
우리가 선언한 변수 유형은 BaseLevel 액터와 다른 액터 사이의 충돌을 감지하는 수단으로 사용할 박스를 나타내는 UBoxComponent 입니다.
앞으로 이동하여 Tick 함수 선언 아래 클래스 파일 맨 아래에 다음 줄을 추가합니다.
protected:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "My Triggers")
UBoxComponent* Trigger;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "My Triggers")
UBoxComponent* SpawnLocation;
Trigger와 SpawnLocation을 이름으로 사용하여 두 개의 UBoxComponents 변수를 생성했습니다.
Trigger UBoxComponent를 사용하여 플레이어 액터가 BaseLevel 액터와 충돌할 때를 감지한 다음 새 레벨 부분을 스폰하고 SpawnLocation UBoxComponent를 사용하여 해당 월드 위치에 액세스하고 해당 값을 스폰 위치로 사용합니다. 새로운 차원의 부분.
이는 레벨을 생성하고 트리거 위치와 SpawnLocation UBoxComponent 위치를 확인할 때 더 명확해집니다.
이 튜토리얼 시리즈의 이전 부분에서 UPROPERTY C++ 매크로를 소개했고 블루프린트 인스턴스에서 변수를 노출하는 데 도움이 된다고 말했습니다.
BlueprintReadWrite 매개변수를 사용하면 예를 들어 청사진에서 이 변수의 값을 읽을 수 있고 청사진에서 이 변수의 값을 변경할 수 있습니다.
기본적으로 이 클래스의 청사진과 다른 청사진에서 이 변수에 액세스하고 조작할 수 있습니다.
EditAnywhere 매개변수는 이 속성을 속성 창에서 편집할 수 있음을 나타냅니다. 기본적으로 블루프린트 편집기의 세부 정보 탭에서 이 변수의 값을 직접 편집할 수 있습니다.
그리고 Category 매개변수는 청사진 편집 도구에 표시될 때 속성의 범주를 지정합니다. 즉 우클릭으로 All Actions For This Blueprint 창을 열면 우리가 생성한 커스텀 카테고리 아래에서 변수를 찾을 수 있다는 뜻입니다. 이 경우에는 My Triggers 입니다.
앞으로 우리가 만든 두 UBoxComponents의 값을 반환하는 함수 두 개를 만들 것입니다:
public:
UBoxComponent* GetTrigger();
UBoxComponent* GetSpawnLocation();
BaseLevel.cpp 파일로 진행하기 전에 전체 BaseLevel.h 파일 클래스를 프로젝트에 복사하여 붙여넣고자 하는 경우를 대비하여 아래에 남겨두겠습니다.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "BaseLevel.generated.h"
class UBoxComponent;
UCLASS()
class SIDERUNNER_API ABaseLevel : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ABaseLevel();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
protected:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "My Triggers")
UBoxComponent* Trigger;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "My Triggers")
UBoxComponent* SpawnLocation;
public:
UBoxComponent* GetTrigger();
UBoxComponent* GetSpawnLocation();
};
BaseLevel.cpp 파일의 상단, 클래스 선언 위와 #include 줄 아래에 다음 줄을 추가합니다.
#include "Components/BoxComponent.h"
이미 언급했듯이 .h 파일에서 전방 선언을 사용한 다음 #include를 사용하여 사용하려는 클래스를 포함합니다.
파일 맨 아래에 다음 코드 줄을 추가합니다.
UBoxComponent* ABaseLevel::GetTrigger(){
return Trigger;
}
UBoxComponent* ABaseLevel::GetSpawnLocation(){
return SpawnLocation;
}
이 줄은 .h 파일에서 선언한 두 함수를 구현할 것입니다. 함수 이름에서 마우스 오른쪽 버튼 클릭 -> 빠른 작업 및 리팩토링 -> 선언 만들기/정의를 통해 함수를 구현할 수도 있습니다.
GetTrigger 함수는 Trigger 변수를 반환하고 GetSpawnLocation은 우리가 선언한 SpawnLocation 변수를 반환합니다.
CTRL + SHIFT + B를 누르거나 Build -> Build Solution으로 이동하여 코드를 컴파일하는지 확인하거나 Unreal Engine 편집기에서도 수행할 수 있습니다.
계속 진행하기 전에 참조할 전체 BaseLevel.cpp 클래스는 다음과 같습니다.
#include "BaseLevel.h"
#include "Components/BoxComponent.h"
// Sets default values
ABaseLevel::ABaseLevel()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ABaseLevel::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ABaseLevel::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
UBoxComponent* ABaseLevel::GetTrigger()
{
return Trigger;
}
UBoxComponent* ABaseLevel::GetSpawnLocation()
{
return SpawnLocation;
}
베이스 레벨 블루프린트 생성
Content -> Blueprints 폴더에서 우클릭 -> New Folder를 클릭하고 이름을 Levels로 지정합니다. Levels 폴더에서 우클릭 -> Blueprint Class.
모든 클래스의 검색 창에서 BaseLevel(기본 수준)을 필터링하고 상위 클래스로 선택합니다.
청사진의 이름을 BP_Level1로 지정합니다. 숫자 때문에 이미 짐작할 수 있듯이 더 정확하게 1에서 10까지 여러 레벨 부분이 있을 것이고 방금 만든 것이 첫 번째 레벨 부분입니다.
먼저 Static Mesh 컴포넌트를 추가하겠습니다. 구성 요소 탭에서 구성 요소 추가 버튼을 클릭하고 정적 메시에 대해 필터링합니다.
Static Mesh의 이름을 Floor로 변경하고 CTRL + C를 누른 다음 CTRL + V를 눌러 복제본을 만들거나 CTRL + D를 사용할 수도 있고 새 Static Mesh의 이름을 Cube로 지정할 수도 있습니다. MacOS의 경우 위에서 언급한 것과 동일한 키인 CMD를 사용합니다.
Add Component 버튼을 클릭하고 Box Collision 검색 필터에서 컴포넌트로 추가합니다. Box Collision to Trigger Box의 이름을 바꾸고 복사본을 만들고 복사본의 이름을 Spawn Location Box로 지정합니다.
앞으로 이동하여 Floor Static Mesh 컴포넌트를 선택하고 디테일 탭에서 Static Mesh : Cube 선택하고, 에 대한 Material 필터 : BasicShapeMaterial를 선택합니다.
다음으로 스케일을 변경하여 바닥 메시의 크기를 조정합니다. 3축 모두 값이 다르기 때문에 값을 변경하기 전에 배율 값의 오른쪽에 있는 잠금 아이콘의 잠금을 해제해야 합니다.
이제 Cube Static Mesh를 선택하고 Static Mesh and Materials 아래의 Details 탭에서 바닥 메시에 대해 했던 것과 동일한 Cube 모델과 동일한 BasicShapeMaterial을 선택합니다.
큐브 메시의 배율 값을 변경하지 않고 Z 위치를 90으로 변경합니다.
Box Collision 구성 요소로 이동하여 Trigger Box 구성 요소를 선택하고 Transform 속성에서 Location 및 Scale에 대해 다음 값을 설정합니다.
마지막으로 Spawn Location Box 구성 요소를 선택하고 Transform 속성에서 Location에 대해 다음 값을 설정합니다.
완료되면 BP_Level1은 다음과 같이 표시됩니다. 전 사이트랑 좀 다르네요 일단 넘어가겠습니다.
이미 언급했듯이 Trigger Box 구성 요소를 사용하여 플레이어 액터가 언제 충돌하는지 감지할 것입니다. 그런 일이 발생하면 Spawn Location Box를 새 레벨 액터가 위치할 위치로 사용하여 새 레벨 액터를 생성합니다. 산란.
그렇기 때문에 플레이어 액터가 충돌할 수 있도록 Trigger Box의 크기를 조정해야 했고, Spawn Location Box를 움직여서 현재 레벨 액터에서 멀리 다음 레벨 액터를 스폰시켜야 했습니다.
블루프린트 에디터에서 클래스 변수 값 설정
더 많은 레벨 파트 생성을 진행하기 전에 BaseLevel.h에서 선언한 Trigger 및 SpawnLocation 변수의 값을 설정해야 합니다.
이렇게 하려면 BP_Level1 블루프린트의 이벤트 그래프 탭으로 이동하여 그래프를 우클릭하고 스폰 위치를 검색합니다:
Set Spawn Location을 찾을 수 있는 카테고리가 My Triggers라는 것을 알 수 있을 것입니다.
SpawnLocation 변수를 선언할 때 UPROPERTY에서 다음과 같이 선언했습니다.
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "My Triggers")
UBoxComponent* SpawnLocation;
UPROPERTY의 마지막 매개 변수는 문자열 값을 사용하는 범주이며 해당 값을 My Triggers로 설정하고 이것이 어디에 반영되는지 확인했습니다.
언제든지 범주 속성을 사용하여 특정 변수에 대한 범주를 정의할 수 있으며 그러면 블루프린트 편집기에서 변수를 검색할 때 지정된 범주 아래에서 해당 변수를 찾을 수 있습니다.
UPROPERTY 매개변수에 대해 말하자면, UPROPERTY에 BlueprintReadWrite 매개변수를 추가했기 때문에 블루프린트 에디터에서 SpawnLocation 변수에만 액세스할 수 있습니다.
UPROPERTY에서 BlueprintReadWrite를 제거하면 SpawnLocation 변수를 찾을 수 없습니다. 따라서 C++ 클래스에서 선언한 변수를 노출하려면 UPROPERTY 매크로를 사용하고 내부에 BlueprintReadWrite 매개변수를 추가하세요.
이제 Spawn Location 변수를 설정하기 위해 그래프의 Components 탭에서 Spawn Location Box 콜리전을 드래그하여 Set Spawn Location 값에 연결합니다.
같은 과정을 반복하되 이번에는 BaseLevel.h 파일에서 선언한 Trigger 변수를 설정합니다. Set Spawn Location 노드가 있는 동일한 범주인 My Triggers 범주에서 Set Trigger 노드를 찾을 수 있습니다.
여기에서 노드를 복사할 수 있습니다.
더 많은 레벨 부품 만들기
앞으로 더 많은 수준의 부품을 만들 것입니다. 콘텐츠 -> 블루프린트 -> 레벨 내부에서 우클릭 -> 새 블루프린트 클래스를 클릭합니다.
이번에는 BaseClass에서 상속하지 않고 대신 생성한 BP_Level1 블루프린트에서 상속합니다.
새 청사진의 이름을 BP_Level2로 지정하고 편집기에서 엽니다. BP_Level2가 BP_Level1과 정확히 같은 것을 알 수 있습니다.
이것은 우리가 BP_Level1을 상속받았기 때문입니다. 즉, 모든 변수와 구성 요소, 이벤트 그래프에 작성한 모든 코드도 상속받습니다.
이벤트 그래프 창으로 이동하여 쉽게 확인할 수 있습니다.
BeginPlay 노드에서 부모 개체의 BeginPlay를 호출합니다. 우리는 상위 개체가 BP_Level1이라는 것을 알고 있으며 해당 청사진의 BeginPlay에 어떤 코드를 넣었는지 알고 있습니다.
다른 레벨 부분을 생성하기 위해 BP_Level1에서 상속한 레벨의 기존 부분을 이동할 수 있습니다. 예를 들어 Cube Mesh 구성 요소의 위치를 변경할 수 있습니다.
또한 Cube Mesh 구성 요소를 복제하고 복제본의 이름을 Cube 2로 바꾸고 위치 및 배율 값을 변경할 수 있습니다.
이제 Cube 2를 복제하고 이름을 Cube 3으로 바꾸고 Transform 속성에서 다음 값을 설정합니다.
그리고 그 변경으로 BP_Level2 청사진을 완성했습니다. 최종 결과는 다음과 같습니다.
이런식으로 레벨10까지 적당히 오브젝트 위치가 크기 등을 조정하여 레벨을 만들어보겠습니다. 적당히 하셔도 되고 그냥 BP_Level1을 열심히 카피하셔도 됩니다.
BP_레벨3:
BP_레벨4:
BP_Level5의 경우 청사진의 일부로 두 개의 스파이크 장애물을 추가하여 플레이하는 사용자에게 게임을 더 어렵게 만들 것입니다.
이를 위해 새로운 Child Actor 컴포넌트를 추가할 것입니다. 구성 요소 추가 버튼을 클릭하고 하위 액터를 필터링한 다음 선택합니다.
Child Actor 컴포넌트의 이름을 Spike 1로 변경한 다음 선택하고 디테일 탭 아래에서 Child Actor Class라는 필드가 있는 Child Actor 컴포넌트 속성을 찾습니다. 드롭다운 목록을 클릭하고 클래스로 BP_Spike를 선택합니다.
Child Actor 구성 요소를 사용하면 다른 블루프린트에서 생성한 다른 블루프린트를 사용할 수 있습니다. 우리가 사용하는 청사진(이 경우 BP_Spike)은 청사진을 생성할 때 정의한 것과 동일한 방식으로 모든 속성을 갖습니다.
다른 구성 요소와 동일하게 Spike 1을 복제하여 복사본을 만들 수 있습니다.
Level5
다른 레벨 청사진으로 이동하면 BP_Level6이 있습니다.
BP_레벨7:
BP_레벨8:
BP_레벨9:
BP_레벨10:
여기에서 갈 곳
이 자습서에서는 Spike 및 BaseLevel 클래스를 만들었습니다. 또한 플레이어 액터가 움직이는 동안 절차적으로 레벨을 생성하는 데 사용할 장애물 청사진과 10개의 레벨 부분을 만들었습니다.
LevelSpawner 클래스 생성 및 절차적 레벨 생성을 사용하여 게임 레벨 생성이라는 제목의 다음 파트에서는 절차적 레벨 생성이라는 기술을 사용하여 레벨을 동적으로 생성하는 방법을 배웁니다.
'언리얼러닝 > 마켓플레이스 코스' 카테고리의 다른 글
Introduction to Your First Hour in Unreal Engine 5.2 (0) | 2023.07.10 |
---|---|
[C++ 게임 만들기 1부] 사이드 스크롤러 : LevelSpawner Class And Procedural Level Generation (0) | 2023.06.28 |
[C++ 게임 만들기 1부] 사이드 스크롤러 : 플레이어 액터 (0) | 2023.06.24 |