이제 본격적으로 캐릭터를 움직이게 해보자
일단 새를 시점으로 플레이할 수 있도록 새의 auto possess player를 Player0으로 설정해주자
이것을 코드로 구현하게되면 아래와 같다.
AutoPossessPlayer = EAutoReceiveInput::Player0;
1. 키바인딩
만약 컨트롤러가 2개이상이라면 첫번째 컨트롤러가 첫번째 플레이어 두번째 컨트롤러가 두번째 컨트롤러를 사용하게 된다.
그리고 이제 키를 Mapping해주자 키는 축 매핑에서 추가해주자
키를 통해 움직이게 하는 콜백하려면 콜백 함수를 할당해주어야 한다.
콜백 함수를 붙여줄 때는 SetupPlayerInputComponent을 통해 한다.
이때 우리가 매핑해준 키의 이름을 잘 알고있어야한다. 지금은 MoveForWard를 매핑해볼 것이니 MoveForWard 이것을 잘 기억해주자
이 때 매핑된 키의 이름과 오브젝트, 콜백함수의 주소를 매개변수로 사용하면된다.
PlayerInputComponent->BindAxis(FName("MoveForward"), this, &ABird::MoveForward);
void ABird::MoveForward(float Value)
{
UE_LOG(LogTemp, Warning, TEXT("Value: %f"), Value);
}
지금은 로그를 통해 눌러지냐를 확인해 보았다.
하지만 이 것은 옛날 인풋시스템 방식으로 이제 Enhanced Input System방식으로 바꿔보자
Pawns폴더에 Input 폴더를 만들어주고 여기에 우클릭해서 입력/입력액션을 추가해주자
그리고 이 입력 액션을 Bird와 이어줄 Input Mapping Context도 추가해주자
이 Input Mapping Context를 Bird 폰 클래스와 연결해주려면 일단 블루프린트에서는 다음과 같이 할 수 있다.
일단 Get Controller와 cast를 통해 폰의 컨트롤러를 가져온다.
가져온 컨트롤러를 Enhanced Input 시스템을 통해 연결해주면 된다. 이때 Priority에 따라 여러 콘텍스트가 작동할지 정해진다.
그리고 만들어둔 입력액션을 사용하려면 블루프린트에서 액션이벤트를 가져온 뒤 원하는 흐름을 추가해주면 된다.
이제 이 과정을 코드로 구현해보자
일단 필요한 함수와 변수를 가져오기 위해 모듈을 가져오는 부분을 수정해주자
Slash.Build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore","EnhancedInput" });
그리고 입력애션과 입력매핑컨텍스트 변수를 헤더파일에서 전방선언해주고 입력액션에 들어갈 함수도 선언해주자
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputMappingContext* BirdMappingContext;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* MoveAction;
//구조체는 헤더파일 가져와야한다.
void Move(const FInputActionValue& Value);
이제 BeginPlay에서 입력컨텍스트에 클래스를 붙여주자
void ABird::BeginPlay()
{
Super::BeginPlay();
//조건문안에 넣는 것이 최적화상으로 좋다
if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem< UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(BirdMappingContext, 0);
}
}
}
또한 입력액션의 콜백함수도 완성해주자
void ABird::Move(const FInputActionValue& Value)
{
const bool CurrentValue = Value.Get<bool>();
if (CurrentValue)
{
UE_LOG(LogTemp, Warning, TEXT("Good"));
}
}
이 콜백 함수를 입력액션에 바인딩 해주자
// Called to bind functionality to input
void ABird::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ABird::Move);
}
}
마지막으로 블루프린트상에서 입력액션과 매핑컨텍스트를 초기화해주면 된다.
이제 본격적으로 폰을 움직여보자
일단 옛날 인풋방식으로 하는것을 보자
플레이어기준 앞을 향하는 벡터를 가지고와서 그방향으로 AddMovementInput을 해주면 된다.
void ABird::MoveForward(float Value)
{
if (Controller && (Value != 0.f))
{
FVector Forward = GetActorForwardVector();
AddMovementInput(Forward, Value);
}
}
그리고 실제로 움직일 수 있게 블루프린트상에 FloatingPawnMovement을 추가해주자
움직이는 모습을 볼 수 있다.
이제 이것을 향상된 인풋시스템으로 바꿔보자
입력 액션에서 타입을 float로 바꿔주고 입력 매핑 컨텍스트에 w키도 받을 수 있게 추가해주자
w키를 눌렀을 때는 w와 반대가 될 수 있도록 Modifiers에 Negate 하나 추가해주자
코드상에서 Value를 받아서 앞으로 움직이게 해주자 함수는 동일하게 AddMovementInput를 사용해주자
void ABird::Move(const FInputActionValue& Value)
{
const float DirectionValue = Value.Get<float>();
if (Controller && (DirectionValue != 0.f))
{
FVector Forward = GetActorForwardVector();
AddMovementInput(Forward, DirectionValue);
}
}
폰이 움직이는 것을 볼 수 있다.
지금상태에서는 어떻게 움직이는지 보이지 않기때문에 카메라를 조정해보도록하자
먼저 블루프린트에서 이 작업을 해보자
첫번째 방법은 카메라 컴포넌트를 루트아래에 두는 것이다. 위치와 각도를 조절하면 탑뷰형태로 볼 수 있다.
하지만 이런 방식보다는 스프링암을 활용하는 것이 좋다.
스프링암은 만약 카메라가 벽과 충돌하게 된다면 줄어들어서 벽 넘어 플레이어를 볼 수 있게 한다.
그리고 팔 길이와 각도도 자유롭게 변경가능하다. 카메라를 돌리는 대신 팔의 각도와 길이를 통해 카메라를 조정하는 효과를 얻는 것이다.
이것을 이제 코드로 구현해보자
우선 스프링암과 카메라를 전방선언을 통해 헤더파일에 선언해주고 cpp파일에서 서브오브젝트를 통해 초기화 해주자
Bird.h
UPROPERTY(VisibleAnywhere)
USpringArmComponent* SpringArm;
UPROPERTY(VisibleAnywhere)
UCameraComponent* ViewCamera;
Bird.cpp
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(GetRootComponent());
SpringArm->TargetArmLength = 300.f;
ViewCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("ViewCamera"));
ViewCamera->SetupAttachment(SpringArm);
이후 핫리로딩을 해주고 각도를 조금 조정해주면 다음과 같은화면이 나오게된다.
이제 앞 뒤뿐만 아니라 원하는 방향으로 움직일 수 있게 해보자 이를 위해 마우스 움직임을 사용할 것이다.
입력 액션을 추가해주자 이때, 2D vector를 받을 수 있게하여 위아래 좌우를 모두 볼 수 있게하자
입력컨텍스트도 xy를 모두 받을 수 있게 추가해주자
이제 코드를 보자면
헤더파일에서는 LookAction에 추가될 액션포인터 변수를 선언해주고 콜백함수도 정의해주자
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* LookAction;
void Look(const FInputActionValue& Value);
cpp파일에서는 선언된 콜백함수를 완성해주고 바인딩해주자
void ABird::Look(const FInputActionValue& Value)
{
const FVector2D LookAxisValue = Value.Get<FVector2D>();
if (GetController())
{
AddControllerYawInput(LookAxisValue.X);
AddControllerPitchInput(LookAxisValue.Y);
}
}
// Called to bind functionality to input
void ABird::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ABird::Move);
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ABird::Look);
}
}
컴파일해준 뒤 블루프린트의 액션칸에 Look 입력액션을 추가해주고 컨트롤러 회전의 피치와 요를 사용할 수 있게 바꿔준다.
결과
입력컨텍스트에서 modifier을 조정하여 자연스럽게 날 수 있도록 조정하자
'게임공부 > Unreal Engine' 카테고리의 다른 글
[Unreal Engine][C++]8. Animation (1) | 2024.07.22 |
---|---|
[Unreal Engine][C++]7. Character Class (0) | 2024.07.18 |
[Unreal Engine][C++]5.Pawn 클래스 (0) | 2024.07.15 |
[Unreal Engine][C++]4. 캐릭터 움직이기 (1) | 2024.07.11 |
[Unreal Engine][C++]3. 디버그 (0) | 2024.07.10 |