이건 블루프린트로 예전에 해본적 있는걸 C++코드로 바꾸는 것 뿐이다. 이걸로 언리얼 C++에 더 익숙해지는 숙련도라고 생각하고 최대한 전부 다 타자로 끝까지 쳤다.
회전
회전을 위해 필요한 재료를 생각해보자.
1. 돌아갈 액터(저번에 만든거 상속 클래스)
2. 회전 함수
3. 회전 속도
4. Tick(매 프레임마다 작동하는거)
이정도라고 볼 수 있다. 나는 여기서 욕심을 한스푼 더 섞어서
5. 회전할 축
까지 넣어보도록 하겠다.
헤더파일
우선 위에서 말한것들을 선언해보자.
#pragma once
#include "CoreMinimal.h"
#include "FloorBase.h"
#include "CH_Rotation_1.generated.h"
UCLASS()
class SETTING_API ACH_Rotation_1 : public AFloorBase
{
GENERATED_BODY()
public:
ACH_Rotation_1();
virtual void Tick(float DeltaTime) override;
protected:
virtual void BeginPlay() override;
//회전 속도
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Settings")
float RotationSpeed;
// 회전 축 결정
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Settings")
FName RotationAxis; // "X", "Y", "Z"로 설정(직관성)
//회전 함수
void RotateActor(float DeltaTime);
};
이렇게 선언을 해주도록 하겠다. 저번에 못본것들만 간단하게 짚고 넘어가도록 하겠다.
virtual void Tick(float DeltaTime) override;
Tick(float DeltaTime) : Tick은 매 프레임마다 작동하는 함수다. 그 안에 DeltaTime이라는 초/프레임 이라는 공식을 가진 친구를 들고가 모든사람에게 시간의 흐름이 같도록 하는 역할을 할것이다.
virtual - override; : 이건 가상함수로 override를 통해 cpp파일에서 재 정의를 할 수 있게 선언해놓는 거라고 보면 된다.
virtual void BeginPlay() override;
BeginPlay() : 게임 실행, 액터 생성 시 작동하는 함수.
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Settings")
UPROPERTY() : C++ 클래스의 멤버 변수를 언리얼 엔진의 리플렉션 시스템에 노출시키는 역할.
EditAnywhere : 이 변수를 언리얼 에디터 디테일 패널에서 값을 수정할 수 있다.
BlueprintReadWrite : 블루프린트에서도 읽고 쓸 수 있도록 함.
Category = "Platform Settings : 에디터의 디테일 패널에서 이 변수가 표시될 카테고리 지정. 구분하기 편하게 그룹화 하는거라고 보면 편하다.
CPP파일
생성자
ACH_Rotation_1::ACH_Rotation_1()
{
static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Game/Resources/Materials/M_Gem_D.M_Gem_D"));
if (MaterialAsset.Succeeded())
{
// SetMaterial 함수 호출하여 머티리얼 적용
SetMaterial(MaterialAsset.Object);
RotationSpeed = 90.0f;
}
}
위에는 액터 만들 때 사용했던거에서 머티리얼을 바꾸고싶어 넣어준 것 뿐이고 그냥 요약하자면
1. 머티리얼 변경
2. 회전속도 = 90
이게 다다.
BeginPlay()
void ACH_Rotation_1::BeginPlay()
{
Super::BeginPlay();
SetActorRotation(FRotator(0.0f, 0.0f, 0.0f));
}
Super::BeginPlay(); : 제일 상위 부모클래스의 BeginPlay()를 먼저 불러오는 역할 언리얼 엔진의 계층적 클래스 구조를 사용할 때 매우 중요한 개념이다.
SetActorRotation() : 이건 그냥 회전도를 설정하는거고 (x,z,y) 축 순서기 때문에 헷갈릴 수 있으니 주의하자. 여기서는 0.0f들로 그냥 초기화 구문으로 봐주면 된다.
RotateActor() 회전 함수
void ACH_Rotation_1::RotateActor(float DeltaTime)
{
if (!FMath::IsNearlyZero(RotationSpeed))
{
if (RotationAxis == "X")
{
AddActorLocalRotation(FRotator(RotationSpeed * DeltaTime, 0.0f, 0.0f));
}
if (RotationAxis == "Y")
{
AddActorLocalRotation(FRotator(0.0f, 0.0f, RotationSpeed * DeltaTime));
}
if (RotationAxis == "Z")
{
AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f));
}
}
}
뭔가 길어보이지만 어떤 축으로 바꿀껀지 나중에 블루프린트에서 수정하기 쉽게하기 위해 늘어트려놓은거고 핵심만 줄여서 보여주겠다.
void ACH_Rotation_1::RotateActor(float DeltaTime)
{
if (!FMath::IsNearlyZero(RotationSpeed))
{
AddActorLocalRotation(FRotator(RotationSpeed * DeltaTime, 0.0f, 0.0f));
}
}
if (!FMath::IsNearlyZero(RotationSpeed)) :이게 뭔지 궁금할 수 있다.
IsNearlyZero() : 이건 0과 가까우면 true로 처리하라는 함수다. RotationSpeed가 부동소수다 보니 0으로 해도 조금씩 움직일 수 있기 때문에 넣어준 것이다.
AddActorLocalRotation(); : 회전을 추가하는 함수. 액터가 현재 방향을 기준으로 어느정도 회전할 것인지 하는것이다. Set은 그냥 그 수치를 적용하는거고 Add는 현재 액터에 추가된다고 보면 편하다.
FRotator(X,Z,Y) : 회전 수치 함수다.
RotationSpeed * DeltaTime : 내가 설정해준 RotationSpeed(회전 속도)에 DeltaTime을 넣어 모든사람이 같은 시간동안 같은 회전속도를 갖게 해주자.
Tick()
void ACH_Rotation_1::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
RotateActor(DeltaTime);
}
Super::Tick() : 상위 클래스의 Tick 함수 불러오기.
RotateActor() : 아까 만든 회전 함수 불러오기.
이렇게 하면 액터 회전은 아주 잘된다.
반복 이동
반복 이동을 위한 재료를 생각해보자.
1. 이동할 액터(저번에 만든거 상속클래스)
2. 이동함수
3. 이동 속도
4. 이동할 거리
5. 이동 방향
6. 이동 축
이정도인거 같다.
헤더파일
#pragma once
#include "CoreMinimal.h"
#include "FloorBase.h"
#include "CH_Move_1.generated.h"
UCLASS()
class SETTING_API ACH_Move_1 : public AFloorBase
{
GENERATED_BODY()
public:
ACH_Move_1();
virtual void Tick(float DeltaTime) override;
//이동속도
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Settings")
float MoveSpeed;
//이동거리
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Settings")
float MaxRange;
// 시작 위치
FVector StartLocation;
//방향
int32 Direction; // 1: 오른쪽, -1: 왼쪽
// 이동 축 결정
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Settings")
FName MoveAxis; // "X", "Y", "Z"로 설정(직관성)
protected:
virtual void BeginPlay() override;
//이동 함수
void MoveActor(float DeltaTime);
};
여기는 위에서 쓴 내용들만으로 이해가 될거라 생각하고 바로 cpp파일로 넘어가겠다.
Cpp파일
#include "CH_Move_1.h"
ACH_Move_1::ACH_Move_1()
{
static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Game/Resources/Materials/M_AlbedoRougness_Master.M_AlbedoRougness_Master"));
if (MaterialAsset.Succeeded())
{
// SetMaterial 함수 호출하여 머티리얼 적용
SetMaterial(MaterialAsset.Object);
}
MoveSpeed = 90.0f;
MaxRange = 200.0f;
Direction = 1;
MoveAxis = "X";
}
void ACH_Move_1::BeginPlay()
{
Super::BeginPlay();
StartLocation = GetActorLocation();
}
void ACH_Move_1::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
MoveActor(DeltaTime);
}
void ACH_Move_1::MoveActor(float DeltaTime)
{
if (!FMath::IsNearlyZero(MoveSpeed))
{
//현재 위치 가져오기
FVector CurrentLocation = GetActorLocation();
//이동거리 계산
FVector NewLocation = CurrentLocation;//위치 업데이트를 위한 변수
float DistanceTravelled = 0.0f;//이동거리 변수
if (MoveAxis == "X")
{
NewLocation.X += MoveSpeed * DeltaTime * Direction;
DistanceTravelled = FMath::Abs(NewLocation.X - StartLocation.X);
}
else if (MoveAxis == "Y")
{
NewLocation.Y += MoveSpeed * DeltaTime * Direction;
DistanceTravelled = FMath::Abs(NewLocation.Y - StartLocation.Y);
}
else if (MoveAxis == "Z")
{
NewLocation.Z += MoveSpeed * DeltaTime * Direction;
DistanceTravelled = FMath::Abs(NewLocation.Z - StartLocation.Z);
}
// 이동 거리 도달 시 이동방향 반전
if (DistanceTravelled >= MaxRange)
{
Direction *= -1; // 방향 반전
StartLocation = NewLocation; // 시작 위치 업데이트
}
//위치 업데이트(이동)
SetActorLocation(NewLocation, true);
}
}
보기만 해선 뭔가 많고 어지러워 보이지만 간단하다.
생성자
ACH_Move_1::ACH_Move_1()
{
static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Game/Resources/Materials/M_AlbedoRougness_Master.M_AlbedoRougness_Master"));
if (MaterialAsset.Succeeded())
{
// SetMaterial 함수 호출하여 머티리얼 적용
SetMaterial(MaterialAsset.Object);
}
MoveSpeed = 90.0f;
MaxRange = 200.0f;
Direction = 1;
}
이동속도 값, 이동 거리, 이동 방향 초기화.
이동 함수
void ACH_Move_1::MoveActor(float DeltaTime)
{
if (!FMath::IsNearlyZero(MoveSpeed))
{
//현재 위치 가져오기
FVector CurrentLocation = GetActorLocation();
//이동거리 계산
FVector NewLocation = CurrentLocation;//위치 업데이트를 위한 변수
float DistanceTravelled = 0.0f;//이동거리 변수
{
NewLocation.X += MoveSpeed * DeltaTime * Direction;
DistanceTravelled = FMath::Abs(NewLocation.X - StartLocation.X);
}
// 이동 거리 도달 시 이동방향 반전
if (DistanceTravelled >= MaxRange)
{
Direction *= -1; // 방향 반전
StartLocation = NewLocation; // 시작 위치 업데이트
}
//위치 업데이트(이동)
SetActorLocation(NewLocation, true);
}
}
이동
FVector CurrentLocation = GetActorLocation();
//이동거리 계산
FVector NewLocation = CurrentLocation;//위치 업데이트를 위한 변수
float DistanceTravelled = 0.0f;//이동거리 변수
NewLocation.X += MoveSpeed * DeltaTime * Direction;
DistanceTravelled = FMath::Abs(NewLocation.X - StartLocation.X);
길어 보이지만 새로운 위치 = 현재 위치 + (이동 속력 x 방향), 이동거리 = (새로운 위치 - 시작 위치)라는 뜻이다
방향 반전
// 이동 거리 도달 시 이동방향 반전
if (DistanceTravelled >= MaxRange)
{
Direction *= -1; // 방향 반전
StartLocation = NewLocation; // 시작 위치 업데이트
}
이동 거리 >= 이동 범위 면 -1을 곱해서 방향을 반대로 돌리는 함수. 그리고 그 시점의 위치를 시작 위치로 업데이트하는거라고 보면 된다.
SetActorLocation(NewLocation, true);
위치 이동함수다. 뒤에 true는 출돌 유무라고 보면됩니다.
'언리얼 공부 > C++' 카테고리의 다른 글
순수가상함수, 추상클래스 그리고 인스턴스 (0) | 2025.02.20 |
---|---|
플로우 차트 (0) | 2025.02.18 |
FPS무기 구조 생각 (0) | 2025.02.17 |
일정 주기로 나왔다 사라지는 발판 (0) | 2025.02.04 |
C++클래스로 액터 생성하고 컴포넌트 추가하기. (1) | 2025.01.23 |