오늘의 목표
- 아침 코드카타
- 과제 7번 필수기능 구현
- 과제 7번 도전기능 구현
아침 코드카타
[문제] 3진법 뒤집기
int solution(int n) {
int trinary = 0;
int answer = 0;
while (n >= 1)
{
trinary = trinary * 10 + n % 3;
n /= 3;
}
int multiplier = 1;
for (int i = 0; trinary>= 1; ++i)
{
answer = answer + multiplier * (trinary % 10);
trinary /= 10;
multiplier *= 3;
}
return answer;
}
int* trinary = (int*) malloc(sizeof(int) * 10);
기억해둘 개념
malloc은 void* 값을 반환하므로 반드시 원하는 포인터 자료형으로 변환시켜줘야한다.
[더 나은 풀이법]
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int solution(int n) {
int answer = 0;
while(n >= 1)
{
answer = (answer * 3) + (n % 3);
n /= 3;
}
return answer;
}
기존에 내가 사용했던 풀이법은 10진법을 기준으로 계산하느라 * 10, / 10 연산을 했는데, 그 연산을 제외하고 3진수 형식으로 3을 곱한 뒤 각 자릿수를 더하는 방식으로 10진수로의 변환도 한 번에 할 수 있다고 한다.
answer = answer * 3 + 나머지
이 수식이 3진수를 10진수로 변환할 때 사용하는 수학 공식을 그대로 계산하는 것과 같다.
7번 과제 필수 기능 구현
액션 바인딩
BeginPlay()
void AMyPawn::BeginPlay()
{
Super::BeginPlay();
if (APlayerController* PC = Cast<APlayerController>(Controller))
{
if (UEnhancedInputLocalPlayerSubsystem * Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
{
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
}
}
1. 컨트롤러 캐스팅
if (APlayerController* PC = Cast<APlayerController>(Controller))
Controller
-Pawn 기본 변수, 이 Pawn을 조종하는 컨트롤러를 가리킴
-APlayerController(플레이어) 혹은 AAIController(AI)일 수 있음
-cast<APlayerController>로 플레이어가 조종중인지 확인
-AI가 조종중이라면 Cast가 nullptr를 반환, if문 스킵
**여기서 선언, 정의 및 존재여부 확인을 동시에 하는 것 같은데?
3. LocalPlayer -> Subsystem 가져오기
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputPlayerSubsystem>(PC->GetLocalPlayer()))
PC -> GetLocalPlayer()
- APlayerController에서 실제 로컬 플레이어 객체(ULocalPlayer)를 가져옴
- 멀티에서는 원격 플레이어도 존재하므로 로컬 플레이어만 입력 처리
ULocalPlayer::GetSubsystem<>()
- UE5의 Subsystem 시스템을 사용해 Enhanced Input 서브시스템을 가져옴
- Subsystem은 UE5에서 특정 기능을 담당하는 싱글턴 매니저 역할
- Enhanced Input 관련 기능은 모두 이 Subsystem을 통해 처리
3. Mapping Context 등록
Subsystem->AddMappingContext(DefaultmappingContext, -0);
DefaultMappingContext : 등록할 UInputMappingContext 에셋 (블루프린트에서 편집 가능하도록 설정함)
0 : 우선순위.
BeginPlay에서 Mapping Context 등록해야하는 이유: 컨트롤러는 게임 시작 후 possess 완료된 뒤에 유효하기 때문에 반드시 BeginPlay 이후에 접근해야 함.
이동 및 회전 로직 구현
헤더 파일
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "InputActionValue.h"
#include "MyPawn.generated.h"
class UCapsuleComponent;
class USkeletalMeshComponent;
class USpringArmComponent;
class UCameraComponent;
UCLASS()
class ASSIGNMENT7_API AMyPawn : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AMyPawn();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CapsuleComponent")
UCapsuleComponent* CapsuleComp;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SkeletalMesh")
USkeletalMeshComponent* SkeletalMeshComp;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpringArm")
USpringArmComponent* SpringArmComp;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera")
UCameraComponent* CameraComp;
UPROPERTY(EditAnywhere, Category = "Input")
class UInputMappingContext* DefaultMappingContext;
UPROPERTY(EditAnywhere, Category = "Input")
class UInputAction* MoveAction;
UPROPERTY(EditAnywhere, Category = "Input")
class UInputAction* LookAction;
void Move(const FInputActionValue& Value);
void Look(const FInputActionValue& Value);
FVector2D CurrentInputVector;
UPROPERTY(EditAnywhere, Category = "Movement")
float MoveSpeed = 500.0f;
};
cpp 파일
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyPawn.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "Components/CapsuleComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
// Sets default values
AMyPawn::AMyPawn()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
CapsuleComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleComponent"));
RootComponent = CapsuleComp;
SkeletalMeshComp = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("SkeletalMeshComponent"));
SkeletalMeshComp->SetupAttachment(CapsuleComp);
SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComponent"));
SpringArmComp->SetupAttachment(CapsuleComp);
SpringArmComp->TargetArmLength = 300.0f;
SpringArmComp->bUsePawnControlRotation = true;
CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
CameraComp->bUsePawnControlRotation = false;
if (CapsuleComp)
{
CapsuleComp->SetSimulatePhysics(false);
}
if (SkeletalMeshComp)
{
SkeletalMeshComp->SetSimulatePhysics(false);
}
}
// Called when the game starts or when spawned
void AMyPawn::BeginPlay()
{
Super::BeginPlay();
if (APlayerController* PC = Cast<APlayerController>(Controller))
{
if (UEnhancedInputLocalPlayerSubsystem * Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
{
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
}
}
// Called every frame
void AMyPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!CurrentInputVector.IsNearlyZero())
{
const FRotator ControlRotation = GetControlRotation();
const FRotator YawRotation(0, ControlRotation.Yaw, 0);
FVector Forward = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
FVector Right = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
FVector Movement = (Forward * CurrentInputVector.Y + Right * CurrentInputVector.X) * MoveSpeed * DeltaTime;
FHitResult Hit;
AddActorWorldOffset(Movement, true, &Hit);
CurrentInputVector = FVector2D::ZeroVector;
}
}
// Called to bind functionality to input
void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyPawn::Move);
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMyPawn::Look);
}
}
void AMyPawn::Move(const FInputActionValue& Value)
{
// 입력값 2D벡터로 가져옴
CurrentInputVector = Value.Get<FVector2D>();
}
void AMyPawn::Look(const FInputActionValue& Value)
{
FVector2D LookInput = Value.Get<FVector2d>();
if (Controller)
{
AddControllerYawInput(LookInput.X);
AddControllerYawInput(LookInput.Y);
}
}
LookInput = Value.Get<FVector2D>();
'Unreal5 공부 > TIL' 카테고리의 다른 글
| 2026/04/22 (0) | 2026.04.22 |
|---|---|
| 2026/4/21 TIL (0) | 2026.04.21 |
| 2026/04/17 TIL (2) | 2026.04.17 |
| 2026/04/16 TIL (0) | 2026.04.16 |
| 2026/04/15 TIL (1) | 2026.04.15 |