[UE] Component 컴포넌트, Player 이동
목차
Source | ||
Characters | ||
CAnimInstance.h .cpp CPlayer.h .cpp |
||
Components | ||
CMontagesComponent.h .cpp .생성 CMovementComponent.h .cpp 생성 CStateComponent.h .cpp 생성 CWeaponComponent.h .cpp 생성 |
||
Utilities | ||
CHelper.h CLog.h .cpp |
||
Global.h CGameMode.h .cpp U2212_06.Build.cs |
||
U2212_06.uproject | ||
Component 만들기 (Movement, State, Montage)
CMovementComponent 생성
새 C++ 클래스 - ActorComponent - CMovementComponent 생성
CMovementComponent.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "CMovementComponent.generated.h"
UENUM()
enum class ESpeedType : uint8
{
Walk = 0, Run, Sprint, Max,
};
UCLASS()
class U2212_06_API UCMovementComponent : public UActorComponent
{
GENERATED_BODY()
private:
UPROPERTY(EditAnywhere, Category = "CameraSpeed")
float HorizontalLook = 45;
UPROPERTY(EditAnywhere, Category = "CameraSpeed")
float VerticalLook = 45;
private:
UPROPERTY(EditAnywhere, Category = "Speed")
float Speed[(int32)ESpeedType::Max] = { 200, 400, 600 };
public:
FORCEINLINE bool CanMove() { return bCanMove; }
FORCEINLINE void Move() { bCanMove = true; }
FORCEINLINE void Stop() { bCanMove = false; }
FORCEINLINE float GetWalkSpeed() { return Speed[(int32)ESpeedType::Walk]; }
FORCEINLINE float GetRunSpeed() { return Speed[(int32)ESpeedType::Run]; }
FORCEINLINE float GetSprintSpeed() { return Speed[(int32)ESpeedType::Sprint]; }
FORCEINLINE bool GetFixedCamera() { return bFixedCamera; }
FORCEINLINE void EnableFixedCamera() { bFixedCamera = true; }
FORCEINLINE void DisableFixedCamera() { bFixedCamera = false; }
public:
UCMovementComponent();
protected:
virtual void BeginPlay() override;
private:
void SetSpeed(ESpeedType InType);
public:
void OnSprint();
void OnRun();
void OnWalk();
void EnableControlRotation();
void DisableControlRotation();
public:
void OnMoveForward(float InAxis);
void OnMoveRight(float InAxis);
void OnHorizontalLook(float InAxis);
void OnVerticalLook(float InAxis);
private:
class ACharacter* OwnerCharacter;
private:
bool bCanMove = true; //이동할 수 있는가
bool bFixedCamera; //카메라 고정인가
};
CMovementComponent.cpp
더보기
#include "Components/CMovementComponent.h"
#include "Global.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"
UCMovementComponent::UCMovementComponent()
{
}
void UCMovementComponent::BeginPlay()
{
Super::BeginPlay();
OwnerCharacter = Cast<ACharacter>(GetOwner());
}
void UCMovementComponent::SetSpeed(ESpeedType InType)
{
OwnerCharacter->GetCharacterMovement()->MaxWalkSpeed = Speed[(int32)InType];
}
void UCMovementComponent::OnSprint()
{
SetSpeed(ESpeedType::Sprint);
}
void UCMovementComponent::OnRun()
{
SetSpeed(ESpeedType::Run);
}
void UCMovementComponent::OnWalk()
{
SetSpeed(ESpeedType::Walk);
}
void UCMovementComponent::EnableControlRotation()
{
OwnerCharacter->bUseControllerRotationYaw = true;
OwnerCharacter->GetCharacterMovement()->bOrientRotationToMovement = false;
}
void UCMovementComponent::DisableControlRotation()
{
OwnerCharacter->bUseControllerRotationYaw = false;
OwnerCharacter->GetCharacterMovement()->bOrientRotationToMovement = true;
}
void UCMovementComponent::OnMoveForward(float InAxis)
{
CheckFalse(bCanMove);
FRotator rotator = FRotator(0, OwnerCharacter->GetControlRotation().Yaw, 0);
FVector direction = FQuat(rotator).GetForwardVector();
OwnerCharacter->AddMovementInput(direction, InAxis);
}
void UCMovementComponent::OnMoveRight(float InAxis)
{
CheckFalse(bCanMove);
FRotator rotator = FRotator(0, OwnerCharacter->GetControlRotation().Yaw, 0);
FVector direction = FQuat(rotator).GetRightVector();
OwnerCharacter->AddMovementInput(direction, InAxis);
}
void UCMovementComponent::OnHorizontalLook(float InAxis)
{
CheckTrue(bFixedCamera);
OwnerCharacter->AddControllerYawInput(InAxis * HorizontalLook * GetWorld()->GetDeltaSeconds());
}
void UCMovementComponent::OnVerticalLook(float InAxis)
{
CheckTrue(bFixedCamera);
OwnerCharacter->AddControllerPitchInput(InAxis * VerticalLook * GetWorld()->GetDeltaSeconds());
}
CStateComponent 생성
새 C++ 클래스 - ActorComponent - CStateComponent 생성
CStateComponent.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "CStateComponent.generated.h"
UENUM()
enum class EStateType : uint8
{
Idle = 0, BackStep, Equip, Hitted, Dead, Action, Max,
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FStateTypeChanged, EStateType, InPrevType, EStateType, InNewType);
UCLASS()
class U2212_06_API UCStateComponent : public UActorComponent
{
GENERATED_BODY()
public:
FORCEINLINE bool IsIdleMode() { return Type == EStateType::Idle; }
FORCEINLINE bool IsBackstepMode() { return Type == EStateType::BackStep; }
FORCEINLINE bool IsEquipMode() { return Type == EStateType::Equip; }
FORCEINLINE bool IsHittedMode() { return Type == EStateType::Hitted; }
FORCEINLINE bool IsDeadMode() { return Type == EStateType::Dead; }
FORCEINLINE bool IsActionMode() { return Type == EStateType::Action; }
public:
UCStateComponent();
protected:
virtual void BeginPlay() override;
public:
void SetIdleMode();
void SetBackStepMode();
void SetEquipMode();
void SetHittedMode();
void SetDeadMode();
void SetActionMode();
private:
void ChangeType(EStateType InType);
public:
FStateTypeChanged OnStateTypeChanged;
private:
EStateType Type;
};
CStateComponent.cpp
더보기
#include "Components/CStateComponent.h"
#include "Global.h"
UCStateComponent::UCStateComponent()
{
}
void UCStateComponent::BeginPlay()
{
Super::BeginPlay();
}
void UCStateComponent::SetIdleMode()
{
ChangeType(EStateType::Idle);
}
void UCStateComponent::SetBackStepMode()
{
ChangeType(EStateType::BackStep);
}
void UCStateComponent::SetEquipMode()
{
ChangeType(EStateType::Equip);
}
void UCStateComponent::SetHittedMode()
{
ChangeType(EStateType::Hitted);
}
void UCStateComponent::SetDeadMode()
{
ChangeType(EStateType::Dead);
}
void UCStateComponent::SetActionMode()
{
ChangeType(EStateType::Action);
}
void UCStateComponent::ChangeType(EStateType InType)
{
EStateType prevType = Type;
Type = InType;
if (OnStateTypeChanged.IsBound())
OnStateTypeChanged.Broadcast(prevType, Type);
}
CMontageComponent 생성
새 C++ 클래스 - ActorComponent - CMontageComponent 생성
CMontageComponent .h
더보기
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Components/CStateComponent.h"
#include "Engine/DataTable.h"
#include "CMontagesComponent.generated.h"
USTRUCT()
struct FMontageData
: public FTableRowBase
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
EStateType Type; //상태 Type
UPROPERTY(EditAnywhere)
class UAnimMontage* Montage;
UPROPERTY(EditAnywhere)
float PlayRate = 1; //Player 속도
};
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class U2212_06_API UCMontagesComponent : public UActorComponent
{
GENERATED_BODY()
private:
UPROPERTY(EditAnywhere, Category = "DataTable")
UDataTable* DataTable;
public:
UCMontagesComponent();
protected:
virtual void BeginPlay() override;
public:
void PlayBackStepMode();
private:
void PlayAnimMontage(EStateType InType);
private:
class ACharacter* OwnerCharacter;
FMontageData* Datas[(int32)EStateType::Max];
};
CMontageComponent .cpp
더보기
#include "Components/CMontagesComponent.h"
#include "Global.h"
#include "GameFramework/Character.h"
UCMontagesComponent::UCMontagesComponent()
{
}
void UCMontagesComponent::BeginPlay()
{
Super::BeginPlay();
if(DataTable == nullptr)//DataTable이 없다면
{ //DataTable이 없다고 메시지를 띄워준다.
GLog->Log(ELogVerbosity::Error, "DataTable is not selected");
return;
}
OwnerCharacter = Cast<ACharacter>(GetOwner());
TArray<FMontageData*> datas;
DataTable->GetAllRows<FMontageData>("", datas);//전체 데이터를 가져온다.
//가져온 데이터를 배열에 넣어준다.
for (int32 i = 0; i< (int32)EStateType::Max; i++)
{
for(FMontageData* data : datas)
{
if((EStateType)i == data->Type)
{
Datas[i] = data;
continue;
}
}//for(data)
}//for(i)
}
//#define LOG_UCMontagesComponent 1
#if LOG_UCMontagesComponent
for (FMontagesData* data : datas)
{
if (data == nullptr)
continue;
FString str;
//Static이 붙는 애들은 Reflection(자료형의 타입을 변수로 다룰 수 있게 해준다).
str.Append(StaticEnum<EStateType>()->GetValueAsString(data->Type));//Enum을 문자열로 바꾸어서 자료형의 이름을 가져온다.
str.Append(" / ");
str.Append(data->Montage->GetPathName());
CLog::Log(str);
}
#endif
void UCMontagesComponent::PlayBackStepMode()
{
PlayAnimMontage(EStateType::BackStep);
}
void UCMontagesComponent::PlayAnimMontage(EStateType InType)
{
CheckNull(OwnerCharacter);
FMontageData* data = Datas[(int32)InType];
if(data == nullptr || data->Montage == nullptr)
{
GLog->Log(ELogVerbosity::Error, "None montages data");
return;
}
OwnerCharacter->PlayAnimMontage(data->Montage, data->PlayRate);//data의 몽타주를 PlayRate속도로 OwnerCharacter에 적용하여 재생.
}
CPlayer 생성
CPlayer.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Components/CStateComponent.h"
#include "CPlayer.generated.h"
UCLASS()
class U2212_06_API ACPlayer : public ACharacter
{
GENERATED_BODY()
private:
UPROPERTY(VisibleAnywhere)
class USpringArmComponent* SpringArm;
UPROPERTY(VisibleAnywhere)
class UCameraComponent* Camera;
private:
UPROPERTY(VisibleAnywhere)
class UCMontagesComponent* Montages;
UPROPERTY(VisibleAnywhere)
class UCMovementComponent* Movement;
UPROPERTY(VisibleAnywhere)
class UCStateComponent* State;
public:
ACPlayer();
protected:
virtual void BeginPlay() override;
public:
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
private:
UFUNCTION()
void OnStateTypeChanged(EStateType InPrevType, EStateType InNewType);
private:
void OnAvoid();
private:
void BackStep();
};
CPlayer.cpp
더보기
#include "Characters/CPlayer.h"
#include "Global.h"
#include "CAnimInstance.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "Components/InputComponent.h"
#include "Components/CMontagesComponent.h"
#include "Components/CMovementComponent.h"
ACPlayer::ACPlayer()
{
CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetMesh());
CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);
CHelpers::CreateActorComponent<UCMontagesComponent>(this, &Montages, "Montage");
CHelpers::CreateActorComponent<UCMovementComponent>(this, &Movement, "Movement");
CHelpers::CreateActorComponent<UCStateComponent>(this, &State, "State");
GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));
USkeletalMesh* mesh;
CHelpers::GetAsset<USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
GetMesh()->SetSkeletalMesh(mesh);
TSubclassOf<UCAnimInstance> animInstance;
CHelpers::GetClass<UCAnimInstance>(&animInstance, "AnimBlueprint'/Game/ABP_Character.ABP_Character_C'");
GetMesh()->SetAnimClass(animInstance);
SpringArm->SetRelativeLocation(FVector(0, 0, 140));
SpringArm->SetRelativeRotation(FRotator(0, 90, 0));
SpringArm->TargetArmLength = 200;
SpringArm->bDoCollisionTest = false;
SpringArm->bUsePawnControlRotation = true;
SpringArm->bEnableCameraLag = true;
GetCharacterMovement()->RotationRate = FRotator(0, 720, 0);
}
void ACPlayer::BeginPlay()
{
Super::BeginPlay();
Movement->OnRun(); //Movement의 기본을 Run으로 설정
Movement->DisableControlRotation();//Movement의 기본을 DisableControlRotation으로 설정
State->OnStateTypeChanged.AddDynamic(this, &ACPlayer::OnStateTypeChanged);
}
void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis("MoveForward", Movement, &UCMovementComponent::OnMoveForward);
PlayerInputComponent->BindAxis("MoveRight", Movement, &UCMovementComponent::OnMoveRight);
PlayerInputComponent->BindAxis("VerticalLook", Movement, &UCMovementComponent::OnVerticalLook);
PlayerInputComponent->BindAxis("HorizontalLook", Movement, &UCMovementComponent::OnHorizontalLook);
PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Pressed, Movement, &UCMovementComponent::OnSprint);
PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Released, Movement, &UCMovementComponent::OnRun);
PlayerInputComponent->BindAction("Avoid", EInputEvent::IE_Pressed, this, &ACPlayer::OnAvoid);
}
void ACPlayer::OnStateTypeChanged(EStateType InPrevType, EStateType InNewType)
{
switch (InNewType)
{
case EStateType::BackStep: BackStep(); break;
}
}
void ACPlayer::OnAvoid()
{
CheckFalse(State->IsIdleMode());
CheckFalse(Movement->CanMove());
CheckTrue(InputComponent->GetAxisValue("MoveForward") >= 0.0f);//뒷방향을 입력했다면
State->SetBackStepMode();//State을 BackStepMode로 변경한다.
}
void ACPlayer::BackStep()
{
Movement->EnableControlRotation();//정면을 바라본 상태로 뒤로 뛰어야하기 때문에 EnableControlRotation으로 만들어준다.
Montages->PlayBackStepMode();//PlayBackStepMode()를 통해 몽타주 재생.
}
이론 설명
UCLASS 접근을 제한하는 방법
- 열어두면 기획이나 디자이너가 접근하여 수정할 수 있다.
- 프로그래머만 접근할 수 있다.
원격 빌드 원리
CI, CD, CD
DevOps
Jenkins ← Repo
↑ push
소스(clinet) 원격빌드
언리얼 에디터 상에서의 작업
StepBack 몽타주 생성
DT_Player (csv. 파일 + DataTable 만들기)
액셀로 csv 파일을 만들어 DT_Player라고 이름 짓고 저장한다.
- 첫번째 열에 인덱스 숫자 기입
- 두번재 열에 Type 이름 넣기 (여기서는 BackStep)
- 세번째 열에 언리얼 내에 저장된 Montage를 레퍼런스 복사하여 넣는다.
- 네번째 열에 PlayRate(재생속도)를 기입한다.
DT_Player
ABP_Player
AnimGraph
실행화면 - Stepback
'⭐ Unreal Engine > UE RPG Weapon System' 카테고리의 다른 글
[UE] AnimNotify, DoAction (0) | 2023.05.08 |
---|---|
[UE] 무기 장착 및 기본 공격하기 (0) | 2023.05.02 |
[UE] 무기 시스템 설계하기 (0) | 2023.05.01 |
[UE] Interface, AnimNotify, Backstep 구현하기 (0) | 2023.04.28 |
[UE] Player 초기 세팅하기 (0) | 2023.04.26 |
댓글
이 글 공유하기
다른 글
-
[UE] 무기 장착 및 기본 공격하기
[UE] 무기 장착 및 기본 공격하기
2023.05.02 -
[UE] 무기 시스템 설계하기
[UE] 무기 시스템 설계하기
2023.05.01 -
[UE] Interface, AnimNotify, Backstep 구현하기
[UE] Interface, AnimNotify, Backstep 구현하기
2023.04.28 -
[UE] Player 초기 세팅하기
[UE] Player 초기 세팅하기
2023.04.26