๐ก C++๋ก ํ๋ ์ด์ด์ ์บ๋ฆญํฐ๋ฅผ ์กฐ์ํ ์ ์๋๋ก ๋ง๋ค์ด ๋ณด์.
C++์ ์ฌ์ฉํด์ ํ๋ ์ด์ด์ ์บ๋ฆญํฐ์๊ฒ W,A,S,D์ Space, ๋ง์ฐ์ค๋ฅผ ์ฌ์ฉํด์ ํ์์ ์ธ ์กฐ์์ด ๊ฐ๋ฅํ๋๋ก ํด๋ณด๊ฒ ์ต๋๋ค.
์ด๋ฒ์๋ Old Input System์ ๋จผ์ ์ฌ์ฉํด์ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
1. Old Input System์ผ๋ก ์กฐ์ ๊ตฌํ
2. Enhanced Input System์ผ๋ก ์กฐ์ ๊ตฌํ
์บ๋ฆญํฐ๋ฅผ ์กฐ์ํ๊ธฐ ์ํ Key ์ถ๊ฐ๋ Blueprint๋ก ๊ตฌํํ ๋์ ๋์ผํ๊ฒ Unreal ์๋ํฐ์์ ์งํํด์ฃผ์ด์ผ ํฉ๋๋ค.
ํด๋ฐ - Edit - Project Settings - Engine - Input์ผ๋ก ์ด๋ํ์ฌ ์๋ ์ฌ์ง๊ณผ ๊ฐ์ด ์ด๋, ๋ง์ฐ์ค ํ์ , ์ ํ์ ๋ํ ํค๋ฅผ ๋ฑ๋กํด์ค๋๋ค.
ํจ์ ๋ํ ๋ณ์์ ๊ฐ์ด ํค๋ํ์ผ์์ ์ ์ธ ํ ์ ์ ๋จ๊ณ๋ฅผ ๊ฑฐ์นฉ๋๋ค.
๊ฐ๊ฐ ์ ๋ ฅ์ ๋ฐ์ธ๋ฉํด ์ค ํจ์๋ฅผ ์ ์ธํฉ๋๋ค.
public:
void LookUp(float value);
void Turn(float value);
SetupPlayerInputComponent ํจ์๋ ACharacter ํด๋์ค๋ก๋ถํฐ ์์๋ ๋ฉค๋ฒ ํจ์๋ก ํ๋ ์ด์ด์ ์ ๋ ฅ์ ๋ฐ์๋ค์ด๊ณ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
SetupPlayerInputComponent ํจ์์์ ๋ฐ์ธ๋ฉ์ ๋ํ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
๋ง์ฐ์ค ํ์ ์ Axis Mappings์์ ์ฒ๋ฆฌํ์ผ๋ BindAxis๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๊ฐ๊ฐ์ ์ธ์๋ ์๋์ ๊ฐ์ต๋๋ค.
// Called to bind functionality to input
void AMyPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis(TEXT("LookUp"), this, &AMyPlayer::LookUp);
PlayerInputComponent->BindAxis(TEXT("Turn"), this, &AMyPlayer::Turn);
}
์ํ๋ Pitch
์ข์ฐ๋ Yaw
๊ฐ๊ฐ ํด๋นํ๋ AddControllerInputํจ์๋ฅผ ํธ์ถํด์ value๋ฅผ ๋ฃ์ด ์ค๋๋ค.
void AMyPlayer::LookUp(float value)
{
AddControllerPitchInput(value);
}
void AMyPlayer::Turn(float value)
{
AddControllerYawInput(value);
}
โ์ ์ฅ ํ ์คํโํด๋ณด๋ฉด ์ข์ฐํ์ ์ ๊ฐ๋ฅํ๋ ์ํํ์ ์ด ๋์ง ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ด๋ SpringArmComp์ bUsePawnControlRotation์ด false๋ก ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด์ ํฌ์คํ ์์ ์ถ๊ฐํ๋ springArmComp์ ์ถ๊ฐ ์ฝ๋๋ฅผ ์์ฑํด์ค๋๋ค.
springArmComp->bUsePawnControlRotation = true;
๋ค์ โ์ ์ฅ ํ ์คํโํด๋ณด๋ฉด ๋ชจ๋ ์ ๋ฉ๋๋ค.
ํน์ ์ํ๊ฐ ๋ฐ๋๋ก ์์ง์ธ๋ค๋ฉด Key Mapping์์ ๊ฐ์ด ๋ฐ๋๋ก ๋ค์ด๊ฐ์ง ์์๋์ง ํ์ธํด์ฃผ์ธ์.
์ด๋๋ ๋์ผํ๊ฒ ์ฒ๋ฆฌ๋ฉ๋๋ค.
3๋จ๊ณ๋ฅผ ๊ฑฐ์น๋ฉด ๋ฉ๋๋ค.
ํ๋ ์ด์ด์ ์ด๋์๋์ ์ด๋๋ฐฉํฅ์ ์ ์ฅํ๊ณ ๊ณ์ฐํ๊ธฐ ์ํด์ walkSpeed์ direction ๋ณ์๋ฅผ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
UPROPERTY(EditAnywhere,Category = PlayerSetting)
float walkSpeed = 600;
FVector direction;
์๋ค ์ด๋ W,S์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ์ํ InputHorizontal ํจ์์
์ข์ฐ ์ด๋ D,A์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ์ํ Input Vertical ํจ์๋ฅผ ์ ์ธํ๊ฒ ์ต๋๋ค.
void InputHorizontal(float vlaue);
void InputVertical(float vlaue);
์ญ์ ํSetupPlayerInputComponent ํจ์์์ ๋ฐ์ธ๋ฉ์ ๋ํ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
// Called to bind functionality to input
void AMyPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
// ์๋ต
PlayerInputComponent->BindAxis(TEXT("Horizontal"), this, &AMyPlayer::InputHorizontal);
PlayerInputComponent->BindAxis(TEXT("Vertical"), this, &AMyPlayer::InputVertical);
}
์ด๋ ๋ฐ์ธ๋ฉ ํจ์์ ์ญํ ์ ํ๋ ์ด์ด์ ์ด๋ ๋ฐฉํฅ ๊ฐ์ ๊ฐ์ ธ์ต๋๋ค.
void AMyPlayer::InputHorizontal(float value)
{
direction.X = value;
}
void AMyPlayer::InputVertical(float value)
{
direction.Y = value;
}
ํ๋ ์ด์ด๊ฐ ์ํ๋ ์ด๋๋ฐฉํฅ์ ์ ์ ์๊ฒ ๋์์ต๋๋ค.
์ด๋ฅผ ํตํด Tick() ํจ์์์ ๊ฐ์ ๊ณ์ฐํ์ฌ ์ค์ ๋ก ์ด๋์ด ๊ฐ๋ฅํ๋๋ก ์ฒ๋ฆฌํ๊ฒ ์ต๋๋ค.
๋ฑ์์ด๋ ๊ณต์์ ์ฌ์ฉํ์ฌ ํ๋ ์ด์ด์ ์ด๋์ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
P(๊ฒฐ๊ณผ ์์น) = P0(ํ์ฌ ์์น) + v(์๋) * t(์๊ฐ)
์ ๊ณต์์ ์ฌ์ฉํด์ ์ฒ๋ฆฌํ๊ฒ ์ต๋๋ค.
void AMyPlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector P0 = GetActorLocation();
FVector vt = direction * walkSpeed * DeltaTime;
FVector P = P0 + vt;
SetActorLocation(P);
direction = FVector::ZeroVector;
}
tick()ํจ์๋ ๊ณ์ํด์ ํธ์ถ๋๊ธฐ ๋๋ฌธ์ ์ค์ ์ ๋ ฅ์ด ์์ ๋๋ง ์ด๋์ ์ํด์๋ direction์ ๊ณ์ฐ์ด ๋๋๋ฉด Zero Vector๋ก ์ด๊ธฐํํด์ฃผ์์ต๋๋ค.
โ์ ์ฅ ํ ์คํโํด๋ณด๋ฉด ํ๋ ์ด์ด๋ฅผ ์์ง์ผ ์ ์์ต๋๋ค.
ํ์ง๋ง ํ๋ ์ด์ด๊ฐ ๋ฐ๋ผ๋ณด๋ ๋ฐฉํฅ์ผ๋ก ์ด๋ํ์ง ์์ต๋๋ค.
์ด๋ direction์ด ๊ฐ์ง๋ ๋ฒกํฐ๊ฐ ์๋ ์ขํ๊ฐ ์๋ ์ ๋ ์ขํ๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด๋ ๋ฐฉํฅ ๋ฒกํฐ๋ฅผ ์ํ์ขํ๋ก ํ๊ธฐ ์ํด์ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์.
direction = FTransform(GetControlRotation()).TransformVector(direction);
GetControlRotationํจ์๋ ํด๋น ํ๋ ์ด์ด ํฐ์ ์ปจํธ๋กคํ๊ณ ์๋ ์ปจํธ๋กค๋ฌ์ ๋ฐฉํฅ์ FRotator ํ์ ์ผ๋ก ๋๊ฒจ ์ค๋๋ค.
๊ทธ๋ฆฌ๊ณ ํน์ ์ด๋ ๋ฒกํฐ๋ฅผ ์์ ์ ๊ธฐ์ค์ผ๋ก ๋ณํํด์ฃผ๋ TransformVector()ํจ์๋ฅผ ์ฌ์ฉํด์ direction์ ์์ ํด์ค๋๋ค.
โ์ ์ฅ ํ ์คํโํด๋ณด๋ฉด ์ด์ ๋ฐ๋ผ ๋ณด๊ณ ์๋ ๋ฐฉํฅ์ผ๋ก ํ๋ ์ด์ด๋ฅผ ์กฐ์ํ ์ ์์ต๋๋ค.
๊ธฐ์กด ์ฐ๋ฆฌ๋ ๋ฑ์ ์ด๋ ๊ณต์์ ์ฌ์ฉํใ ์ฌ ์์ง์์ ์ง์ ๊ตฌํํ์์ต๋๋ค.
ํ์ง๋ง ์ธ๋ฆฌ์ผ ๊ฒ์ ํ๋ ์์ํฌ์๋ ์บ๋ฆญํฐ์ ์์ง์์ ์ฒ๋ฆฌํด์ค Charactor Movement๋ผ๋ ์ปดํฌ๋ํธ๊ฐ ์์์ต๋๋ค.
์ด ์ปดํฌ๋ํธ์ ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ๋ฑ์์ด๋ ๊ตฌํ ์ฝ๋๋ฅผ ์์ ํ๊ฒ ์ต๋๋ค.
๊ธฐ์กด ๊ณ์ฐ ๊ณต์์ ์ฃผ์์ฒ๋ฆฌํ๊ณ , AddMovementInput์ด๋ผ๋ ํจ์๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
void AMyPlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
direction = FTransform(GetControlRotation()).TransformVector(direction);
//FVector P0 = GetActorLocation();
//FVector vt = direction * walkSpeed * DeltaTime;
//FVector P = P0 + vt;
//SetActorLocation(P);
AddMovementInput(direction);
direction = FVector::ZeroVector;
}
โ์ ์ฅ ํ ์คํโํด๋ณด๋ฉด ๋์ผํ๊ฒ ๋์ํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
์ ํ๋ ์บ๋ฆญํฐํด๋์ค์ ๊ธฐ๋ฅ ์ค Jump()๋ฅผ ํธ์ถํด์ฃผ๋ฉด ๋์ ๋๋ค.
๋ฐ์ธ๋ฉ ํจ์๋ฅผ ๋จผ์ ์ ์ธํ๊ฒ ์ต๋๋ค.
public:
void LookUp(float value);
void Turn(float value);
void InputJump();
์ด๋ฒ์ BindAction์ ์ฌ์ฉํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ธ์๊ฐ ํ๋ ๋ ์ถ๊ฐ๋ฉ๋๋ค.
// Called to bind functionality to input
void AMyPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//์๋ต
PlayerInputComponent->BindAction(TEXT("Jump"), IE_Pressed, this, &AMyPlayer::InputJump);
}
์์ ๊ฐ์ด ํจ์๋ฅผ ๋ฐ์ธ๋ฉํ๋ค๋ฉด InputJump()๋ฅผ ์๋์ ๊ฐ์ด ์ ์ํด์ค๋๋ค.
void AMyPlayer::InputJump()
{
Jump();
}
์ด๊ฒ ๋์ ๋๋ค.
โ์ ์ฅ ํ ์คํโํด๋ณด๋ฉด ์บ๋ฆญํฐ๊ฐ ์ ํ๊น์ง ๊ฐ๋ฅํด์ง๋๋ค.
์บ๋ฆญํฐ์๊ฒ Old Input System์ ์ฌ์ฉํด์ ๊ธฐ์ด์ ์ธ ์์ง์์ด ๊ฐ๋ฅํ๋๋ก ๊ตฌํํ์ต๋๋ค.
๋ค์ ํฌ์คํ ์๋ Enhanced Input System์ ์ฌ์ฉํด์ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
1. Old Input System์ผ๋ก ์กฐ์ ๊ตฌํ
2. Enhanced Input System์ผ๋ก ์กฐ์ ๊ตฌํ