Unreal Engine 5/Tutorial

[Unreal Engine 5] 섹션3: 장애물 공격

SW Developer 2024. 4. 4. 00:01

섹션3: 장애물 공격

: 언리얼 엔진5에서 장애물을 공격하는 프로젝트를 제작해보자

<<

 

[Project Plan]

  1. Create a project with our assets
  2. Install the tools we need for C++
  3. Learn some C++ basics
  4. Make a platform the moves
  5. Configure out moving platform
  6. Send the platform back
  7. Rotating platforms

프로젝트 셋업

 

① Market Place에서 아래 키트와 케릭터를 다운받는다.

 

② Create Project (UE 4.7 버전에서 구동가능하다)

프로젝트를 생성한 후, UE 버전을 5.0으로 바꿔준다.

 

그리고 실행하면....!

와우...!

 

③ Save Current Level As 클릭 후 Content > Main으로 저장

 

Settings> Project Settings 에서 Default로 저장

 

④ Content > SCK_Casual01 > Blueprints에 있는 ThirdPersonCharacter을 맵에 삽입

 

골프 게임 같다

 

 


Customizing The Character

 

케릭터를 커스텀화해보자!

 

① 블루 프린트 > Create Child Blueprint Class

 

Name을 BP_ThirdPersonCharacter로 설정한 뒤 Content에 저장

 

Select를 누르면 아래 화면이 생성된다

 

 

Details > auto 검색 > Auto Possess Player를 Player 0으로 설정

 

→ 이제 기본 플레이어가 위 마네킹으로 설정된다.

 

 

② 케릭터의 3인칭 카메라가 켜지지 않는 문제 해결하기

 

Content > Casual > 블루 프린트 > ThirdPersonCharacter 더블클릭

 

들어가보면, 컴파일 에러가 2개 생성되어 있다.

돋보기 버튼을 누르면 어떤 노드에서 오류가 발생했는지 그 위치를 확인할 수 있다

 

우클릭 후 TurnRightRate 가져오기

 

가져온 후 ctrl키를 눌러 기존 Exec 핀 위치를 변경해준다

 

동일하게 아래 오류노드도 수정해준다

 

우클릭 후 TurnRight 노드 가져와서 수정

 

컴파일 후 저장

 

→ 이제 3인칭 카메라가 정상적으로 작동한다

 

 

③ 케릭터 커스텀화 하기

 

BP_ThirdPersonCharacter > Mesh (CharacterMesh0) 선택

 

Details에서 Skeletal Mesh 변경하기

                                                ↓

 

아래와 같이 변경된다

 

Main으로 돌아가 Play해보면 케릭터가 아래와 같이 변경된 것을 확인할 수 있다

 

 


Compiler & Editor

 

① Visual Studio 

- C++를 사용한 게임 개발 설치

 

- Unreal Engine 설치 관리자 설치

 

- .NET 6.0 설치

 

https://dotnet.microsoft.com/ko-kr/download/dotnet?cid=getdotnetcore

 

② Visual Studio Code

- Extensions > C/C++,Unreal Engine 4 Snippets 설치

 


Compiling a C++ Project

 

 

① Editor 바꾸기

- Edit > Editor Preferences

 

- Source Code > Editor를 Visual Studio Code로 변경

 

② C++ 클래스 생성하기

Tools > New C++ Class

Actor 선택

 

- Class 이름을 MovingPlatform으로 설정 (스페이스 X)

 

③ Visual Studio Code열기

 

- Tools > Open Visual Studio Code

- 프로젝트 파일 경로 내 Code Workspace 파일 열기

 

③ Terminal > Run Build Task > ObstacleAssaultEditor Win64 Development Build

실행중인 Editor는 종료해야 한다.

 

아래 메시지가 뜨면 완료된 것이다.

강의에 사용된 UE5 패키지 버전들이 서로 호환이 안된다...그래서 그냥 5.3에서 했다

 

그리고 프로젝트를 다시 실행하면, 아래 C++ Classes 내에 생성된 MovingPlatform을 확인할 수 있다.

 


UPROPERTY Variables

 

① 블루프린트에서 보이려면, 표시해야할 변수가 있다는 것을 알려줘야 한다

 

- MovingPlatform.h의 public 맨 하단에 아래 코드를 추가한다.

UPROPERTY(EditAnywhere)
int32 MyInt = 99;

 

② 라이브 코딩

언리얼 엔진 에디터를 끄지 않고도 코딩할 수 있게 한다

 

③ 컴파일이 완료되면, MovingPlatform의 Details에 아래와 같이 변수가 추가된 것을 확인할 수 있다.

신기방기

 

- 아래와 같이, float형,bool형 변수도 추가한 후 다시 컴파일 해보자.

UPROPERTY(EditAnywhere)
float MyFloat = 5.99;

UPROPERTY(EditAnywhere)
bool MyBool = true;

굿잡

 


Live Coding Issues

 

라이브 코딩은 Editor의 변경 사항에만 영향을 미치고 디스크에 영구적으로 저장하지는 않는다.

 

→ 변수의 값을 Editor에서 변경해도, 변경된 값이 Editor의 Actor에 저장되지는 않는다. 데이터가 사라진 채로 저장될 수도 있다.

 

해결방법

① Editor를 닫은 후, VSCode에서 Ctrl+Shift+B로 재빌드한다.

→ 에디터를 닫은 채로, 에디터 밖에서 전체를 다시 컴파일해야 한다

 

② Edit > Editor Preferences > Live Coding > Enable Live Coding 비활성화하기

 


C++ Files & BeginPlay

 

※ Editor에서 실행할 함수는 cpp에 입력한다.

 

MovingPlatform.cpp > BeginPlay 함수에서 MovingPlatform.h에서 정의한 변수에 엑세스해보자

 

① BeginPlay 아래에 다음 코드를 추가한다

void AMovingPlatform::BeginPlay()
{
	Super::BeginPlay();
	
	MyInt = 9;
}

 

 

② 그리고 게임에서 Play하면, 기본값이 99로 설정되어 있던 MyInt값이 9로 변경된다.

Outliner > MovingPlatform 선택 후 Details에서 확인

 

③ 간단한 계산기 만들기

 

- MovingPlatform.h에 int형 변수 InputA,B,APlusB 추가

UPROPERTY(EditAnywhere)
int32 InputA = 0;

UPROPERTY(EditAnywhere)
int32 InputB = 0;

UPROPERTY(EditAnywhere)
int32 APlusB = 0;

 

- MovingPlatform.cpp의 BeginPlay 아래에 다음 코드 추가

APlusB = InputA + InputB;

 

- Compile 후 BeginPlay하기 전에, Details에 InputA,B 값 입력

 

- BeginPlay

: BeginPlay 실행 후, InputA와 InputB의 연산이 실행되어 아래처럼 두 값의 합산값이 계산된다

 

+ 같은 방법으로 Float형도 추가하기

 


Using Structs In C++

 

① Vector 변수 선언하기

UPROPERTY(EditAnywhere)
FVector MyVector = FVector(1,2,3);

 

※ 구조체형 변수 앞에는 F를 붙인다

 

 

② float형 변수MyX 선언 후, cpp에서 BeginPlay 뒤에 MyVector의 X값을 할당

 

- MovingPlatform.h

UPROPERTY(EditAnywhere)
float MyX = 0;

 

 

- MovingPlatform.cpp

Super::BeginPlay();
MyX = MyVector.X;

 

 

③ MyVecotr의 Y값을 MyX로 선언

MyVector.Y = MyX;

 

- Editor에서 MyX 값을 5로 변경

 

- Play버튼을 누르면 아래와 같이 Y의 값이 MyX값으로 변경된다 

 

 


Calling Functions in C++

C++에서 함수를 호출해보자

 

① SetActorLocation 함수 호출 후, FVector 인자 삽입

SetActorLocation(FVector(1,2,3));

 

② MovingPlatform에 위치 추가하기

컴포넌트만 위치를 지정할 수 있으므로, MovingPlatform Actor에 큐브를 추가한다.

 

 

그리고 MovingPlatform을 더블클릭하면, MovingPlatform의 위치로 이동할 수 있다.

 

그리고 아래 Detach 버튼을 눌러,

 

MovingPlatform의 위치를 확인해보면, 1,2,3으로 되어 있는 것을 알 수 있다.

 

 

③ ThirdPerson의 위치를 우클릭하여 복사한 후, MovingPlatform의 위치를 해당 위치로 옮긴다

 

- MovingPlatform.cpp에서 BeginPlay이후 Location을 MyVector로 설정

SetActorLocation(MyVector);

 

- ThirdPerson의 위치 복사

마우스 우클릭 하여 복사

 

- MovingPlatform의 MyVector에 붙여넣기

 

- Play버튼을 누르면 아래처럼 Cube의 위치가 옮겨진다

 

 


TICK

 

Game Loop란?

1. Process Input

2. Update game state

3. Render to display

→ Frame이라고 부른다 (동영상을 구성하는 하나의 그림)

 

Frame rate: 컴퓨터가 1초당 계산할 수 있는 프레임 수를 말한다

 

→ 언리얼에서는 Tick함수를 사용해 게임 루프의 중간 단계를 진행한다

 

① Tick 아래에 아래 코드 추가 (MyVector의 Z값 +1)

void AMovingPlatform::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	MyVector.Z=MyVector.Z + 1;

	SetActorLocation(MyVector);
}

 

② Compile 후 Play

Cube의 Z값이 계속해서 +1 된다

 

③ Y값 +1 증가로 코드 변경

MyVector.Y = MyVector.Y + 1;
SetActorLocation(MyVector);

 

④ Compile 후 Play하면 아래처럼 Y축 방향으로 계속 움직인다

Cube 높이가 살짝 높아서 뛰면서 캡쳐해서 그런지 웃기게 돼버렸다ㅋㅋ

 


Local Variables

 

Scope?

변수가 유지되는 기간을 의미한다

 

 

① MovingPlatform.cpp에 지역변수 LocalVector 추가 후,초기값을 MyVector로 초기화하고 Z값을 +100

FVector LocalVector = MyVector;
LocalVector.Z = LocalVector.Z + 100;

MyVector.Y = MyVector.Y + 1;
SetActorLocation(LocalVector);

→ LocalVector의 Z값을 +100하고, MyVector의 Y값도 +1씩 변경한다

 

하지만, Cube의 Z값이 +100씩 바뀌지는 않는다.

여전히 Y+1씩 움직임

 

 

② Editor에서 Play버튼 후 빠져나와서 Moving Platform의 Location 확인하기

 

- 초기 Location

 

- Play버튼 후 MovingPlatform의 Location

Z값이 +100 되었다

 

→ 지역변수는 함수가 특정한 실행을 마쳤을 때, 사라지고 초기화된다

(클래스 변수는 다른 함수로 인해 언제든 업데이트 될 수 있다)

 

- MovingPlatform.h에서 Tick이 실행될때마다 MyVector는 업데이트 되기 때문임

class MYPROJECT_API AMovingPlatform : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AMovingPlatform();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UPROPERTY(EditAnywhere)
	FVector MyVector = FVector(1,2,3);

};

 

 


Pseudo Code

 

Pseudo Code?

알고리즘에서 사용할 단계를 일반적인 언어로 설명한 것이다

 

Comment(주석)

컴파일러에서 무시하는 코드를 말한다. 주석을 사용하여 pseudo code를 작성할 수 있다.

 

VSCode에 아래와 같이 주석을 달아본다.

// Move platform forwards
    // Get current location
    // Add vector to that location
    // Set the location
// Send platform back if gone too far
    // Cheeck how far we've moved
    // Reverse direction of motion if gone too far

 

 


Function Return Values

 

Expression

Fragment of code that produces a value

 

ex) MyVector, LocalVector.Z+100, GetActorLocation()

 

Statement

An action to be performed

 

① GetActorLocation, SetActorLocation으로 기존 코드 대체하기

 

- 기존코드

FVector LocalVector = MyVector;
LocalVector.Z = LocalVector.Z + 100;
MyVector.Y = MyVector.Y + 1;
SetActorLocation(LocalVector);

 

 

- 대체코드

FVector CurrentLocation = GetActorLocation();
SetActorLocation(CurrentLocation);

 

 

② MovingPlatform의 위치 설정 후 Play 버튼

 

③ MovingPlatform이 X+1씩 이동하는 것을 볼 수 있다

 

 


Velocity & Deltatime

 

속도 항목을 추가해서 전체 벡터를 한번에 지정해보자

 

① MovingPlatform.h에 새로운 카테고리 Moving Platform 및 FVector 추가

UPROPERTY(EditAnywhere, Category="Moving Platform")
FVector PlatformVelocity = FVector(100, 0, 0);

 

② MovingPlatform.cpp에 CurrentLocation에 PlatformVelocity 추가

//CurrentLocation.X = CurrentLocation.X + 1; (기존 코드)
CurrentLocation = CurrentLocation + PlatformVelocity;

 

③ MovingPlatform Actor 내 카테고리인 Moving Platform에 FVector가 추가된다

 

④ DeltaTime을 활용하여, PlatformVelocity 실행간격 조절하기

CurrentLocation = CurrentLocation + PlatformVelocity * DeltaTime;

→ 1s에 100cm(FVector 설정값)씩 움직이게 된다

 

 

※ DeltaTime: 언리얼에서 각 프레임이 어느 정도의 간격으로 실행될지 결정하는 시간 변수

 


Scope Resoultion Operator

(범위 지정 연산자)

 

① MovingPlatform.h에 StartLocation 설정 후, cpp에서 GetActorLocation으로 위치 가져오기

 

- MovingPlatform.h 

FVector StartLocation; //C++에서만 사용하므로, UPROPERTY는 하지 않음

 

- MovingPlatform.cpp

void AMovingPlatform::BeginPlay()
{
	Super::BeginPlay();
	StartLocation = GetActorLocation();
}

 

② cpp에서 FVector 내 Dist 함수를 활용하여, StartLocation과 CurrentLocation 사이의 거리 출력

 

- MovingPlatform.h에 DistanceMoved float형 변수 선언

UPROPERTY(VisibleAnywhere)
float DistanceMoved = -1;

 

- MovingPlatform.cpp에 거리를 DistanceMoved에 할당

// Send platform back if gone too far
    // Cheeck how far we've moved
DistanceMoved = FVector::Dist(StartLocation, CurrentLocation); //순서 안 중요함

 

③ Play 버튼을 눌러 Distance 확인하기

 

- 기본값: -1.0

 

- Play 버튼 클릭

100cm/s 씩 이동하는 것을 확인할 수 있다

 


If Statements

 

If문을 활용하여 일정 거리만큼 이동했을 때, 이동방향을 반대로 바꿔보자

 

① MovingPlatform.h에 float형 변수 MoveDistance를 100으로 초기화

UPROPERTY(EditAnywhere, Category="Moving Platform")
float MoveDistance = 100;

 

② MovingPlatform.cpp에 DistanceMoved를 지역변수로 변경 후, if문 작성

    // Set the location
SetActorLocation(CurrentLocation);
// Send platform back if gone too far
    // Cheeck how far we've moved
float DistanceMoved = FVector::Dist(StartLocation, CurrentLocation);
    // Reverse direction of motion if gone too far
if(DistanceMoved > MoveDistance)
{
    PlatformVelocity = -PlatformVelocity;
    StartLocation = CurrentLocation;//시작점을 현재위치로 초기화
}

 

③ Play 버튼을 누른 후, 100만큼 이동하면 MovingPlatform의 이동방향이 반대가 된다

 

 


Using Member Functions

 

Actor가 MoveDistance만큼 이동했을 때,

끝 점을 지나치지 않고 정확히 끝 점에서 끝나도록 설정하기

 

PlatformVector의 법선벡터를 가져온 후, 총 이동할 거리만큼 StartLocation을 변경하기

FVector MoveDirection = PlatformVelocity.GetSafeNormal();
StartLocation = StartLocation + MoveDirection * MoveDistance;
SetActorLocation(StartLocation);

 

 


Blueprint Child Classes

블루프린트의 Child 클래스 만들기

 

 ① C++ 클래스에서 MovingPlatform 우클릭 후 블루프린트 Class 생성하기

 

앞에 BP_를 붙여 Content에 생성

 

 

② Content Drawer에서 필터 > Static Mesh 삽입하기

 

 

삽입하면 아래처럼 DefaultSceneRoot 아래에 추가된다.

 

그리고 StaticMesh를 원점에서 살짝 벗어나도록 이동시킨다

 

그리고 BP_MovingPlatform을 선택한 후,

 

PlatformVelocity = (0,0,200)으로 설정, MoveDistance = 500으로 설정한다

 

③ ContenDrawer로 돌아가, 방금 생성한 BP_MovingPlatform을 삽입한다

 

④ Play버튼을 누르면, 방금 삽입한 클래스가 위,아래로 움직인다

 

 

⑤ 블루프린트에서 Object를 XY평면 아래로 배치한다

 

※ Object 선택 후 우클릭하면, 선택한 객체로 View를 설정할 수 있다

 

위와 같이 설정하면, 돌기둥이 바닥을 뚫고 내려갔다가 올라온다

 


Forcing Character Collisions

 

케릭터가 장애물과 충돌하도록 만들기

 

① MovingPlatform에서 새로운 Child 클래스 생성하기

BP_PusingCube

 

Box형태의 StaticMesh 삽입

 

자물쇠 표시를 누른 후 스케일 100배 하기

 

BP_PushingCube를 선택한 후, Velocity와 MoveDistance 설정

 

Content Drawer에서 해당 박스를 삽입하기

 

② Play버튼을 눌러 케릭터와 충돌시켜본다

→ 케릭터의 기본 코드는, 케릭터가 움직이기 전에는 object와 충돌하지 않는다

 

③ BP_ThirdPersonCharcter를 선택한 후, 블루프린트 버튼에서 Open Blueprint Editor

 

Character Movement를 선택한 후,

 

블루프린트 이벤트 그래프 우클릭 후 MoveUpdatedComponent 추가

- Delta: 얼마나 멀리 이동할지 결정

- Sweep: 이동하는 중에 발생하는 충돌을 탐지

 

④ EventTick을 추가하여 연결

→ 지금처럼 연결할 경우, Tick 함수 발생 시마다 자동으로 케릭터가 X,Y 1씩 이동한다

 

따라서, 새로운 MoveUpdatedComponent를 추가하여 반대방향으로 Delta를 설정해준다.

→ 지금처럼 설정하면, 이제 케릭터가 Object와 충돌할 때 자연스럽게 움직이게 된다

 

지금까지 만든 클래스들로 아래와 같이 만들어본다

 

 

⑤ Get Actor Rotation를 추가하여 연결한다

→ 이제 Actor를 회전시킬 수 있게 됐다

 


GameMode

 

Object 선택 후 우클릭하여, Play From Here에서 Play를 시작할 수 있다

 

 

GameMode란?

→ 레벨에 들어가서 게임 규칙을 관리하는 액터

(누가 어디에 스폰해야 하는지, 플레이어가 어떤 클래스를 사용할 지 등의 게임 작동방식 정의)

 

① 블루프린트 버튼 클릭

 

- Project Settings: 프로젝트 전체에 대한 설정으로, 프로젝트에서 생성한 모든 레벨에 대한 기본 게임 모드

- World Override: 특정레벨에 대한 게임 모드

 

② Project Settings > Create > GameModeBase 선택

 

③ BP_ObstacleAssaultGameMode 라고 명명 후 Save

 

새로운 창이 실행된 후, Class Defaults를 선택

 

- Details 내 Classes 섹션 > Default Pawn Class를 변경

 

④ World Override > Select GameModeBase Class > None 선택

 

이제 Project Settings로 변경된 것을 알 수 있다.

 

⑤ Player Start를 삽입한 후, Play 버튼 혹은 Object 선택 후 우클릭하여 Play from here

 

- 이제 정상적으로 작동한다!

 

 


Writing To The Output Log

 

사용자 로그에서 원하는 문구를 출력하기

 

① Unreal Engine 4 Snippets를 설치하면, 문구를 자동으로 완성해준다.

 

② UE_LOG 구문 작성하기 (ulog)

UE_LOG(LogTemp,Display, TEXT("Your message"));

 

- LogTemp: 로그 카테고리 유형

- Display: 로그의 긴급 수준

- TEXT: 출력할 텍스트

 

 

③ Play버튼을 누른 후, Output Log 확인

 

: ` 버튼을 2번 눌러서 실행할 수도 있다

 

→ MovingPlatform의 씬에 있는 모든 Actor에 대해 메시지를 출력하기 때문에 여러 번 출력됨

 

 

④ Display, Warning, Error 메세지 출력해보기

UE_LOG(LogTemp, Display, TEXT("Your message"));
UE_LOG(LogTemp, Warning, TEXT("Your message"));
UE_LOG(LogTemp, Error, TEXT("Your message"));

 

 

⑤ MoveDistance 변수 출력하기

UE_LOG(LogTemp, Display, TEXT("Congifured Moved Distance: %f"), MoveDistance);

 

 

 

⑥ if문에 Overshoot 변수 추가 후 출력하기

if(DistanceMoved > MoveDistance)
{
    float OverShoot = DistanceMoved - MoveDistance;
    UE_LOG(LogTemp, Display, TEXT("Platform overshot by %f"), OverShoot);
    
    PlatformVelocity = -PlatformVelocity;
    FVector MoveDirection = PlatformVelocity.GetSafeNormal();
    StartLocation = StartLocation + MoveDirection * MoveDistance;
    SetActorLocation(StartLocation);
}

 

 


FString

 

여러 개의 문자, 즉 문자열 출력하기

 

① FString 변수로 문자열을 초기화한 후, UE_LOG에 추가하기

FString MyString = "My String Value";
UE_LOG(LogTemp, Display, TEXT("Here's My String: %s"), *MyString);

 

※ 언리얼에서는 FString 문자열을 출력할 때, 변수형 앞에 *를 사용해야 한다

(언리얼 내부에서 MyString을 바로 인식하지는 못하기 때문)

 

 

 

② Dynamic Value 출력하기

FString Name = GetName();
UE_LOG(LogTemp, Display, TEXT("BeginPlay: %s"), *Name);

 

 

→ 나중에 오버슛이 발생했을 때, 로그 메시지에 Actor의 이름을 출력하면 문제를 찾기 더 쉬워진다

 

③ If문에 GetName()을 추가하여 Actor 출력하기

FString Name = GetName();
UE_LOG(LogTemp, Display, TEXT("%s Platform overshot by %f"), *Name, OverShoot);

 

 


Member Functions

 

멤버 함수를 사용하여, 지금까지 작성한 코드를 함수로 정리해보자

 

① MovingPlatform.h에 private으로 멤버함수 MovePlatform의 원형 제공하기

private:

	UPROPERTY(EditAnywhere, Category="Moving Platform")
	FVector PlatformVelocity = FVector(100, 0, 0);

	UPROPERTY(EditAnywhere, Category="Moving Platform")
	float MoveDistance = 100;

	FVector StartLocation;

	void MovePlatform(float DeltaTime);

 

→ DeltaTime은 Tick함수에서 받아오는 값이므로, 새로운 변수를 지정하여 해당 값을 받아와야 한다

 

② MovingPlatform.cpp에서 MovePlatform 함수 정의하기

void AMovingPlatform::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	MovePlatform(DeltaTime);
}

void AMovingPlatform::MovePlatform(float DeltaTime)
{
	FVector CurrentLocation = GetActorLocation();
	CurrentLocation = CurrentLocation + PlatformVelocity * DeltaTime;
	SetActorLocation(CurrentLocation);
	float DistanceMoved = FVector::Dist(StartLocation, CurrentLocation);
	
	if(DistanceMoved > MoveDistance)
	{
		float OverShoot = DistanceMoved - MoveDistance;
		FString Name = GetName();
		UE_LOG(LogTemp, Display, TEXT("%s Platform overshot by %f"), *Name, OverShoot);
		PlatformVelocity = -PlatformVelocity;
		FVector MoveDirection = PlatformVelocity.GetSafeNormal();
		StartLocation = StartLocation + MoveDirection * MoveDistance;
		SetActorLocation(StartLocation);
	}

}

 

→ Tick함수에서 사용된 DeltaTime의 값이 MovePlatform의 인자로 전달된다

 

③ RotatePlatform 함수 정의하기

 

- MovingPlatform.h에 함수 원형 제공하기

void RotatePlatform(float DeltaTime);

 

- MovingPlatform.cpp에서 RotatePlatform 함수 정의하기

void AMovingPlatform::RotatePlatform(float DT)
{
	UE_LOG(LogTemp, Display, TEXT("%s Rotating..."), *GetName());
}

 

 


Return Statements

 

반환문 작성하기

 

① MovingPlatform.h에 bool형 ShouldPlarformReturn 함수 원형 제공하기

bool ShouldPlatformReturn();

 

② MovingPlatform.cpp에 ShoudlPlarformReturn 함수 정의

bool AMovingPlatform::ShouldPlatformReturn()
{
	float DistanceMoved = FVector::Dist(StartLocation, GetActorLocation());
	return DistanceMoved > MoveDistance;
}

→ 기존 if문 내의 DistanceMoved > MoveDistance를 추상화

 

③ 기존 MovePlatform 내 코드 정리하기

void AMovingPlatform::MovePlatform(float DeltaTime)
{
	if(ShouldPlatformReturn())
	{
		FVector MoveDirection = PlatformVelocity.GetSafeNormal();
		StartLocation = StartLocation + MoveDirection * MoveDistance;
		SetActorLocation(StartLocation);
		PlatformVelocity = -PlatformVelocity;
	}

	else
	{
		FVector CurrentLocation = GetActorLocation();
		CurrentLocation = CurrentLocation + PlatformVelocity * DeltaTime;
		SetActorLocation(CurrentLocation);
	}
}

 

④ MovingPlatform.cpp 내 ShouldPlarformReturn의 DistanceMoved 추상화

- 헤더파일에 float형 변수를 return하는 GetDistanceMoved 함수 원형 제공

float GetDistanceMoved();

 

- cpp파일에 GetDistanceMoved 함수 정의

float AMovingPlatform::GetDistanceMoved()
{
	return FVector::Dist(StartLocation, GetActorLocation());
}

 

→ ShouldPlatformReturn 함수 코드 재작성

bool AMovingPlatform::ShouldPlatformReturn()
{
	//float DistanceMoved = FVector::Dist(StartLocation, GetActorLocation());
	return GetDistanceMoved() > MoveDistance;
}

 


Const Member Functions

 

Member 함수가 다른 클래스의 어떤 상태도 변경하지 않도록 const를 붙인다

 

① 헤더파일에 선언한 ShouldPlarformReturn,GetDistanceMoved 함수 뒤에 const 붙이기

bool ShouldPlatformReturn() const;
float GetDistanceMoved() const;

 

② CPP파일에 정의한 함수에도 const 붙이기

bool AMovingPlatform::ShouldPlatformReturn() const
{
	return GetDistanceMoved() > MoveDistance;
}

float AMovingPlatform::GetDistanceMoved() const
{
	return FVector::Dist(StartLocation, GetActorLocation());
}

 

※ const 함수 내에서는 const인 함수만 사용가능하다

 

 


FRotator

 

회전 변수형 FRotator를 만들어 RotatePlatform 제작하기

 

① 헤더파일에 새로운 카테고리 추가 후, FRotator형 변수 RotationVelocity 추가

UPROPERTY(EditAnywhere, Category= "Rotation")
FRotator RotationVelocity;

 

② CPP파일에 RotatePlatform 함수 정의하기

void AMovingPlatform::RotatePlatform(float DeltaTime)
{
	AddActorLocalRotation(RotationVelocity * DeltaTime);
}

→ 기존 Location방식처럼, Actor의 Location을 받아와서 LocationVelocity값을 그냥 더하는 방식으로는 회전자를 제어할 수 없다. (회전은 데이터 구조상 오버플로우가 발생하기 때문인 것으로 추측됨)

 

③ 이제 Editor로 돌아가면, MovingPlatform 카테고리 내에 Rotation Velocity가 추가되어 있음을 알 수 있다.

 

④ Rotation Velocity의 Z값을 90으로 지정한 후 Play

 

⑤ MovingPlatform Class의 파생 블루 프린트 클래스 생성

BP_RotatingPlatform

 

 

⑥ 해당 블루 프린트 클래스에서 StaticMesh 삽입 후, BP_RotatingPlatform(Self)의 Details 변경

Move Factor 다 삭제 후, Rotation을 Z축 기준으로 90도씩 회전하도록

 

⑦ Play 버튼 클릭

계단이 돌아간다...

 


Level Design & Polish

 

지금까지 제작한 Class들을 활용한 Level Design 하기

 

 

▶ 우리가 활용할 수 있는 옵션엔 어떤 것들이 있는가?

- Moving (Up/Down/Left/Right)

- Rotating

- Pushing/Transporting

 

 

Level Design 컨셉 계획하기

실제 에픽게임즈 개발자의 기획 ㄷㄷ

 

 

② 실제 맵에 Mesh들 배치하기

 

옮기고자 하는 위치에 있는 object의 로케이션 값을 복사해서 사용하면 편리하다

 

③ 케릭터가 Object를 이동할 수 없을 때 → ThirdPersonCharacter 설정값 변경

 

- BP_ThirdPersonCharacter 블루 프린트 실행 > Movement > Details

Walkable Floor Angle이 44도 이상일 경우, 오를 수 없다 (계단 경사 등)

 

④ 회전하는 MovingPlatform 블루 프린트 하위 Class인 BP_Sweeper 추가하기

 

⑤ 컨셉대로 Map에 Object 배치하기

와 이거 배치하는거 상노가다다.....하지만 뭔가 이걸로 건축하면 재밌을지도..?

 

 

※ Object 폴더 정리 깔끔하게 해주기!

 

 

 

 

 

 

 

 

 

 

 

※ 해당 게시글은 개인 학습의 목적으로, 아래 강의를 수강한 후 정리한 학습노트입니다.

https://www.udemy.com/share/108sS83@2ZG2vOuhe6q6GMVRAgJykLf63W_6PvbHfSH-eLgJ8if3KfTc8Xx-E9MW6XQGjj12gg==/