PlayerController Input Action Input Mapping Context FInputActionValue UEnhancedInputLocalPlayerSubsystem AddControllerYawInput() BlueprintInitializeAnimation, Convert to Validated Get Control Rig Cached Pose const FInputActionValue& valuePlayerController 클래스가 UInputMappingContext* 가짐.nullptr 생성 후 블루프린트에서 넣기.LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>()Subsystem->AddMappingContext(InputMappingContext, 0);EnhancedInput->BindAction( PlayerController->MoveAction, ETriggerEvent::Triggered, this, &ASpartaCharacter::Move );AddControllerYawInput(LookInput.X);AddMovementInput(GetActorForwardVector(), MoveInput.X)n, m이 주어진다.n, 세로 길이가 m인 직사각형을 *로 출력한다.n = 5, m = 3이면 *****를 3줄 출력한다.#include <iostream>
#include <string>
using namespace std;
int main(void) {
int n;
int m;
string rect;
cin >> n >> m;
for (int i = 0 ; i < n ; i++) rect.push_back('*');
for (int j = 0 ; j < m ; j++) cout << rect << '\n';
return 0;
}
for - cout 여러번 반복할 필요 없이 string 에 더할 것string row(n, '*');를 사용하면 push_back 반복문 없이 별 문자열을 바로 만들 수 있다.int main(void)
{
int n;
int m;
cin >> n >> m;
string row(n, '*');
for (int i = 0; i < m; i++) cout << row << '\n';
return 0;
}
for - cout 여러번 반복할 필요 없이 string 에 더할 것push_back()은 문자열 뒤에 문자 하나를 추가할 때 사용할 수 있다. append()는 여러개string row(n, '*'); 형태로 만들 수 있다.'\n'은 endl보다 단순 줄바꿈에 적합하며, 불필요한 flush가 없어 일반적으로 더 가볍다. PlayerControllerClass = ASpartaPlayerController::StaticClass(); GameMode 생성자에 집어넣으면 됨.Input Mapping System (IMC) : Input Action들 총괄해서 관리
Input Action (IA)
IA는 전선, IMC는 스위치
우리 캐릭터가 하는 행동
Inputs) 우클릭으로 Input - Input Action 만들기.bool 걍 누르고 떼는 스위치Axis1D : float 값 단일 축. 전진/후진, 가속 페달Axis2D : 축 2개.Axis3D : 축 3 개 동시 처리. 비행 시뮬레이션 같은 것.Pressed : 누를 때만 작동Released : 뗄 때 작동 Negate : 입력값 반전Scalar : 입력값 배율 추가Swizzle Input Axis Values : 입력 축 변경 (X-Y 등)Input 연결해 주면 됨Move 의 경우엔 Swizzle 잘 해주고Look 의 경우
//SpartaPlayerController.h
//미리선언
class UInputMappingContext;
class UInputAction;
public:
ASpartaPlayerController();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input");
UInputMappingContext* InputMappingContext;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input");
UInputAction* MoveAction;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input");
UInputAction* JumpAction;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input");
UInputAction* LookAction;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input");
UInputAction* SprintAction;
protected:
virtual void BeginPlay() override;
//SpartaPlayerController.cpp
#include "EnhancedInputSubSystems.h"
ASpartaPlayerController::ASpartaPlayerController()
: InputMappingContext(nullptr),
MoveAction(nullptr),
JumpAction(nullptr),
LookAction(nullptr),
SprintAction(nullptr)
{
}
void ASpartaPlayerController::BeginPlay()
{
Super::BeginPlay();
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
{
if (InputMappingContext)
{
Subsystem->AddMappingContext(InputMappingContext, 0);
}
}
}
}
UPROPERTY 붙여서 포인터 생성nullptr 화 해서 안전하게LocalPlayer : 현재 플레이어 컨트롤러에 연결된 플레이어 객체EnhancedInputLocalPlayerSubsystem : 입력을 "받는" 서브시스템if라인에서 Subsystem 이란 이름의 객체 생성도 같이 한다.Subsystem->AddMappingContext(InputMappingContext, 0); : 실제로 우리가 만든 Input Mapping Context 집어넣는 곳. 0 은 우선도다.IA 를 활성화 할 뿐Local Player - 일종의 플레이어. 사용자. 그래서 얘가 IMC를 들고 있게 된다.
//SpartaCharacter.h
//미리선언
struct FInputActionValue;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
UFUNCTION() // 리플렉션 적용용. 블루프린트에서 수정할 필요는 없다.
void Move(const FInputActionValue& value);
UFUNCTION()
void StartJump(const FInputActionValue& value);
UFUNCTION()
void StopJump(const FInputActionValue& value);
UFUNCTION()
void StartSprint(const FInputActionValue& value);
UFUNCTION()
void StopSprint(const FInputActionValue& value);
UFUNCTION()
void Look(const FInputActionValue& value);
StartJump StopJump 같이 bool 값을 받는 Input Action의 경우 시작과 끝 함수를 구분해서 지정하는 게 일반적이다
const FInputActionValue& value : FInputActionValue 는 구조체. 크기가 큼. 그래서 &으로 참조만.
Sprint 위한 멤버 변수들은 private에 저장
//SpartaCharacter.cp
#include "SpartaPlayerController.h"
#include "EnhancedInputComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
//생성자에서 멤버변수 초기화
NormalSpeed = GetCharacterMovement()->MaxWalkSpeed;
SprintSpeedMultiplier = 1.7f;
SprintSpeed = NormalSpeed * SprintSpeedMultiplier;
void ASpartaCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
if (UEnhancedInputComponent* EnhancedInput = Cast<UEnhancedInputComponent>(PlayerInputComponent))
{
if (ASpartaPlayerController* PlayerController = Cast<ASpartaPlayerController>(GetController()))
{
if (PlayerController->MoveAction)
{
EnhancedInput->BindAction(
PlayerController->MoveAction,
ETriggerEvent::Triggered,
this,
&ASpartaCharacter::Move
);
}...
MoveAction SprintAction 등에 함수 불러오는 BindAction 실행하면 된다.ETriggerEvent::Completedvoid ASpartaCharacter::Move(const FInputActionValue& value)
{
if (!Controller) return;
const FVector2D MoveInput = value.Get<FVector2D>();
if (!FMath::IsNearlyZero(MoveInput.X))
{
AddMovementInput(GetActorForwardVector(), MoveInput.X);
}
if (!Controller) return; 컨트롤러 체크Jump, GetCharacterMovement 등 플레이어컨트롤러 없으면 작동 안하는 함수들 이용하면 if(!Controller) return; 필요없다FVector2D.X 식으로 받기.IsNearlyZero 는 부동소수점 처리용bool 값은 value.Get<bool>()void ASpartaCharacter::StopSprint(const FInputActionValue& value)
{
//if (!Controller) return;
if (GetCharacterMovement())
{
GetCharacterMovement()->MaxWalkSpeed = NormalSpeed;
}
}
AddControllerYawInput(LookInput.X); | 시스템 기획 | 콘텐츠 기획 |
|---|---|
| 전투 메커니즘, 데미지 공식 | 어떤 적이 등장하고, 어떤 패턴을 가지는가 |
| 퀘스트 시스템 구조 | 어떤 퀘스트 이야기가 있는가 |
| 아이템 등급 체계 | 어떤 아이템이 존재하는가 |
| 강화 시스템 규칙 | 강화 재료를 어디서 얼마나 얻는가 |
| 레벨 에디터 도구 | 어떤 레벨이 만들어지는가(레벨기획 = 컨텐츠 기획) |
| 지표 | 의미 | 업계 평균 (모바일 기준) |
|---|---|---|
| D1 리텐션 | 첫날 플레이 후 다음 날 재접속 비율 | 30~40% |
| D7 리텐션 | 7일 후 재접속 비율 | 10~20% |
| D30 리텐션 | 30일 후 재접속 비율 | 5~10% |
| D90 리텐션 | 90일 후 재접속 비율 | 2~5% |
ABP_Character
Event BlueprintInitializeAnimation 이 BeginPlay 역할Get Owning Actor 써도 된다. Try to get Pawn Owner 도 같은 역할이겠지만.Cast To 하고 Get Character Movement 해서 레퍼런스 변수로 세팅해 두기 Event BlueprintUpdateAnimation : 에니메이션 업데이트 할 때마다Get 할 때마다 Convert to Validated Get 으로 검사 후 Get 할 수 있음.CharacterMovement - Get Velocity - Vector Length XYbIsFalling 도 만들어두기
Locomotive State Machine 생성. Idle WalkRun State 생성. 조건은 bShouldMove 로. WalkRun 은 준비된 BlendSpace 1D 사용
Settings - Set Initial Transforms From MeshControl Rig Class : 발 조정 용이므로 BasicFootIK 설정ShouldDoIKTrace : Jump 안할 때만 Trace 할 것이므로 Use Pin 설정. 이걸 bIsFalling 하고 연결New Save cached PoseState Alias 이용 : 특정 State 들에서 조건 만족하면 이 State로 전환한다는 노드To Land State Alias 노드 만들어 Jump, FallLoop 노드에 체크 해 두고Land State에 연결. 조건은 !bIsFallingLand 애니메이션은 Additive Animation이다 : 다른 Animation과 더해야 함.
bShouldMove Idle 로 이동할 수 있도록 Transition - Automatic Rule Based on Sequence Player in StateMM_Land 애니메이션에서 Play Loop 체크 해 놓아야 함에 주의! 여러 버그나, Additive 더하는 동안 생길 문제를 방지할 수 있다.ToFalling State Alias 추가. Locomotion, Land State일 때 공중모션으로 전환될 수 있도록.ToFalling->Jump : bIsFalling 체크하고 Velocity.Z > 50 활용ToFalling->FallLoop : Velocity.Z <= 50 부분만 다르다.Jump -> FallLoop : Automatic Rule 로 점프 애니메이션 재생된 후에 FallLoop로 가도록 한다.FallLoop는 Play Loop 체크, 점프는 필요없음.