Body
-body01
-body01_NRM ->normal
-body01_SPEC -> specular
EyeL1
-eye_iris_L
EyeR1
-eye_iris_R
Eyebase
- 수정안함
Eyeline
- eyeline
Face
-face00
Hair
-hair base
-hair NRM ->normal
-hair SPEC -> specular
Skin
-skin01
mat_cheek
- cheek00
이동 하기전에 물리 법칙 영향 받는지 체크하고 결과가 나옴 ( --> 물리연산 --> 입력 연산 -> 결과 )
Add Movement Input 함수
이동 벡터 추가
물리 기반 이동
프레임 독립성
프레임 독립적
으로 동작합니다. Set Actor Location 함수는 캐릭터나 오브젝트의 위치를 직접적으로 설정하는 함수입니다.
다음은 Add Movement Input과 Set Actor Location의 주요 차이점입니다
Euler (gimbal lock)
https://www.youtube.com/watch?v=zc8b2Jo7mno
Gimbal Lock을 해결하는 방법
Unreal Engine 와 Gimbal Lock
현제 월드내에 기준으로 값을 처리하는 이동 방식이라 어디를 바라보는 월드 기분 앞뒤 옆으로 이동 한다
바라보는 시점 마다 움직임을 주기 위한 Get Control Rotation 사용해서 제어 해보자
제어 되고 있는 회전 값
구현 된 점프 사용
언리얼 공식 문서에 등록된 회전 입력 값을 처리하는 함수를 정의 해보려고 한다
CTPSPlayer.cpp
ACTPSPlayer::ACTPSPlayer()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
ConstructorHelpers::FObjectFinder<USkeletalMesh> InitMesh(TEXT("/Script/Engine.SkeletalMesh'/Game/MyResource/UnityChanForUE/unitychan.unitychan'"));
if(InitMesh.Succeeded())
{
GetMesh()->SetSkeletalMesh(InitMesh.Object);
//메쉬 위치 조정
GetMesh()->SetRelativeLocationAndRotation(FVector(0, 0, -90), FRotator(0, -90, 0));
}
}
CTPSPlayer.h
public:
// Sping Arm 컴포넌트 생성
UPROPERTY(VisibleAnywhere, Category = Camera)
class USpringArmComponent* SpringArmComp;
UPROPERTY(VisibleAnywhere, Category = Camera)
class UCameraComponent* CameraComp;
CTPSPlayer.cpp
#include "GameFramework\SpringArmComponent.h"
#include "Camera\CameraComponent.h"
ACTPSPlayer::ACTPSPlayer()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
ConstructorHelpers::FObjectFinder<USkeletalMesh> InitMesh(TEXT("/Script/Engine.SkeletalMesh'/Game/MyResource/UnityChanForUE/unitychan.unitychan'"));
if(InitMesh.Succeeded())
{
GetMesh()->SetSkeletalMesh(InitMesh.Object);
GetMesh()->SetRelativeLocationAndRotation(FVector(0, 0, -90), FRotator(0, -90, 0));
}
// SpringArm 초기화, 기본 값 설정
SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp"));
SpringArmComp->SetupAttachment(RootComponent);
SpringArmComp->SetRelativeLocationAndRotation(FVector(0, 0, 50), FRotator(-20, 0, 0));
SpringArmComp->TargetArmLength = 530;
SpringArmComp->bUsePawnControlRotation = true;
// 카메라 초기화
CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComp"));
CameraComp->SetupAttachment(SpringArmComp);
CameraComp->bUsePawnControlRotation = false;
bUseControllerRotationYaw = true;
}
IMC ( Input Mapping Context )
IA ( Input Action )
전방선언 (Forward Declaration)
CTPSPlayer.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h" // 추가
#include "CTPSPlayer.generated.h"
// 전방 선언
class UInputMappingContext;
class UInputAction;
UCLASS()
class MAGICIAN_API ACTPSPlayer : public ACharacter
{
.. 생략 ..
UPROPERTY(EditAnywhere, Category = Input)
UInputMappingContext* PlayerMappingContext;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* MoveIA;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* LookUpIA;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* TurnIA;
void Move(const FInputActionValue& value);
void LookUp(const FInputActionValue& value);
void Turn(const FInputActionValue& value);
UPROPERTY(VisibleDefaultsOnly)
FVector MoveDirection;
};
CTPSPlayer.cpp
... 생략...
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "InputAction.h"
... 생략
void ACTPSPlayer::BeginPlay()
{
Super::BeginPlay();
if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
{
// #include "EnhancedInputSubsystems.h 헤더 참조
if(UEnhancedInputLocalPlayerSubsystem* Subsystem
= ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(PlayerMappingContext, 0);
}
}
}
void ACTPSPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
// EnhancedInputComponent.h 참조
// 바인딩 해당 함수 호출 바인딩
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked< UEnhancedInputComponent>(PlayerInputComponent))
{
EnhancedInputComponent->BindAction(MoveIA, ETriggerEvent::Triggered, this, &ACTPSPlayer::Move);
EnhancedInputComponent->BindAction(LookUpIA, ETriggerEvent::Triggered, this, &ACTPSPlayer::LookUp);
EnhancedInputComponent->BindAction(TurnIA, ETriggerEvent::Triggered, this, &ACTPSPlayer::Turn);
EnhancedInputComponent->BindAction(JumpIA, ETriggerEvent::Triggered, this, &ACTPSPlayer::Jump);
}
}
Move
void ACTPSPlayer::Move(const FInputActionValue& value)
{
// 입력 값을 FVector 형태로 가져옴
const FVector _CurrentValue = value.Get<FVector>();
// Controller가 유효할때
if (Controller)
{
//MoveDirection 벡터에 입력된 X, Y 값을 설정
MoveDirection.Y = _CurrentValue.X; // 좌우 방향 값
MoveDirection.X = _CurrentValue.Y; // 전후 방향 값
}
// 카메랑의 현재 회전에 맞춰서, MoveDirection을 변환
// 캐릭터가 입력한 방향이 월드 좌표계가 아닌 플레이어가 바라보는 방향으로 이동
MoveDirection = FTransform(GetControlRotation()).TransformVector(MoveDirection);
// [ 위치 - 스케일 - 회전 ]
// 변환된 MoveDirection 방향으로 캐릭터를 이동
// 실제 캐릭터를 이동시키는 역할
AddMovementInput(MoveDirection);
MoveDirection = FVector::ZeroVector;
}
LookUp
void ACTPSPlayer::LookUp(const FInputActionValue& value)
{
// 입력 값을 float 형태로 가져옵니다
const float _CurrentValue = value.Get<float>();
// 카메라의 pitch 값을 변경하여 위아래 시점 이동을 수행합니다
AddControllerPitchInput(_CurrentValue);
}
Turn
void ACTPSPlayer::Turn(const FInputActionValue& value)
{
// 입력 값을 float 형태로 가져옵니다
const float _CurrentValue = value.Get<float>();
// 카메라의 Yaw 값을 변경하여 좌우 시점 이동을 수행합니다
AddControllerYawInput(_CurrentValue);
}
Input Action
IMC
CTPSPlayer.h
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* JumpIA;
void InputJump(const FInputActionValue& value);
CTPSPlayer.cpp
void ACTPSPlayer::InputJump(const FInputActionValue& value)
{
Jump();
}