본문 바로가기

언리얼엔진/ThirdPersonTemplete

프로젝트 만들기 - TPSPlayer

P231112이라는 제목으로  C++타입빈프로젝트를 하나 만든다 .

프로젝트명Build.cs에  "EnhancedInput","Niagara" 를 추가하고 언리얼에디터, VS를 끄고 프로젝트실행파일 위를 우클릭후 VS솔루션을 다시만든후 리빌드해준다. 

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", 
			"EnhancedInput","Niagara" });

 

EnhancedInput방식이므로 InputAction과 InputContextMapping파일을 만든다.

 

만드는 법은 이곳을 참조하세요

2023.10.17 - [언리얼레퍼런스/게임플레이프레임워크] - UE5 Enhanced Input

 

TPSPlayer라는 클래스를 하나 만든다.

TPSPlayer.h  클래스명 앞에  프로젝트명이 붙었다. 나중에 복붙하실분들은 이걸 자신의 프로젝트명으로 바꾸던지 클래스 안쪽만 카피하시길 바란다.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputAction.h"
#include "TPSPlayer.generated.h"

class UInputMappingContext;
class UInputAction;


UCLASS()
class P231113_API ATPSPlayer : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	ATPSPlayer();

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;

public:

	UPROPERTY(VisibleAnywhere, Category = "Camera")
	class USpringArmComponent* springArmComp;

	UPROPERTY(VisibleAnywhere, Category = "Camera")
	class UCameraComponent* cameraComp;

	UPROPERTY(VisibleAnywhere, Category = "Fire")
	class UStaticMeshComponent* weaponMeshComp;

	UPROPERTY(EditAnywhere, Category = "FX")
	class UNiagaraComponent* niagaraFX;

	UPROPERTY(EditAnywhere, Category = "Input")
	UInputMappingContext* PlayerMappingContext;

	UPROPERTY(EditAnywhere, Category = "Input")
	UInputAction* MoveIA;

	UPROPERTY(EditAnywhere, Category = "Input")
	UInputAction* LookUpIA;

	UPROPERTY(EditAnywhere, Category = "Input")
	UInputAction* TurnIA;

	UPROPERTY(EditAnywhere, Category = "Input")
	UInputAction* JumpIA;

	UPROPERTY(EditAnywhere, Category = "Input")
	UInputAction* FireIA;

public:
	void Move(const FInputActionValue& Value);
	void LookUp(const FInputActionValue& Value);
	void Turn(const FInputActionValue& Value);
	void InputJump(const FInputActionValue& Value);
	void InputFire(const FInputActionValue& Value);

public:
	UPROPERTY(EditAnywhere, Category = "Move")
	float moveSpeed;

	UPROPERTY(EditAnywhere, Category = "Fire")
	TSubclassOf<class APBullet> magazine; //총알오브젝리퍼런스

	UPROPERTY(EditAnywhere, Category = "Animation")
	UAnimMontage* attackAnimMontage;  //공격애니메이션


private:
	void Locomotion(); //이동 애니메이션

	FVector moveDirection;  //이동방향
	bool fireReady;  //총알준비상태
	float fireTimerTime;

public:
	UPROPERTY(EditAnywhere, Category = "Fire")
	float fireCoolTime;
protected:
	void FireCoolTimer(float Duration, float deltaTime);

public:
	void SpawnBullet(); //총알 발사
	void ShowFX();  //Niagara를 보여주는 효과
};

PBullet.h를 참조하므로 아직 컴파일하며 안된다.

나이아가라FX는 아직 만들지 않았으므로 참조를 막아두었다. 널포인트 체크를 안해 이대로 실행하면 에러가 난다.

TPSPlayer.cpp 

// Fill out your copyright notice in the Description page of Project Settings.
#include "TPSPlayer.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "NiagaraComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "PBullet.h"

// Sets default values
ATPSPlayer::ATPSPlayer()
{
	// 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 라는 유틸리티로 에셋 가져오기(찾기)
	ConstructorHelpers::FObjectFinder<USkeletalMesh> initMesh(TEXT("/Script/Engine.SkeletalMesh'/Game/MyResource/unitychan.unitychan'"));

	if (initMesh.Succeeded()) //제대로 오브젝트를 가져왔다면 ~ 
	{
		GetMesh()->SetSkeletalMesh(initMesh.Object);

		//Relative - > 상대적 위치값, 회전값
		GetMesh()->SetRelativeLocationAndRotation(FVector(0, 0, -88), 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;

	//moveSpeed = 100;

	//메쉬컴포넌트 생성
	weaponMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WeaponMesh"));
	//캐릭터 메쉬에 부착  
	weaponMeshComp->SetupAttachment(GetMesh(), FName("Character1_RightHandSocket"));

	fireCoolTime = 1.85f;
	fireTimerTime = 0;
	fireReady = true;
}

// Called when the game starts or when spawned
void ATPSPlayer::BeginPlay()
{
	Super::BeginPlay();

	if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem
			= ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			Subsystem->AddMappingContext(PlayerMappingContext, 0);
		}
	}

	//niagaraFX = GetComponentByClass<UNiagaraComponent>();
	//niagaraFX->SetVisibility(false);
}

// Called every frame
void ATPSPlayer::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	Locomotion();

	if (!fireReady)
	{
		FireCoolTimer(fireCoolTime, DeltaTime);
	}
}

// Called to bind functionality to input
void ATPSPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
//입력 바인딩
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		EnhancedInputComponent->BindAction(MoveIA, ETriggerEvent::Triggered, this, &ATPSPlayer::Move);
		EnhancedInputComponent->BindAction(LookUpIA, ETriggerEvent::Triggered, this, &ATPSPlayer::LookUp);
		EnhancedInputComponent->BindAction(TurnIA, ETriggerEvent::Triggered, this, &ATPSPlayer::Turn);
		EnhancedInputComponent->BindAction(JumpIA, ETriggerEvent::Triggered, this, &ATPSPlayer::InputJump);
		EnhancedInputComponent->BindAction(FireIA, ETriggerEvent::Triggered, this, &ATPSPlayer::InputFire);
	}
}

void ATPSPlayer::Move(const FInputActionValue& Value)
{
	const FVector _currentValue = Value.Get<FVector>();

	if (Controller)
	{
		moveDirection.Y = _currentValue.X;
		moveDirection.X = _currentValue.Y;
	}
}

void ATPSPlayer::LookUp(const FInputActionValue& Value)
{
	//mouse y - 한 축의 값 (float)
	const float _currentValue = Value.Get<float>();
	AddControllerPitchInput(_currentValue);
}

void ATPSPlayer::Turn(const FInputActionValue& Value)
{
	//mouse x  - 한 축의 값 (float)
	const float _currentValue = Value.Get<float>();
	AddControllerYawInput(_currentValue);
}

void ATPSPlayer::InputJump(const FInputActionValue& Value)
{
	Jump();
}

void ATPSPlayer::InputFire(const FInputActionValue& Value)
{
	if (fireReady)
	{
		UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
		if (AnimInstance)
		{
			AnimInstance->Montage_Play(attackAnimMontage);
		}

		fireReady = false;
	}
}

void ATPSPlayer::Locomotion()
{
	//이동방향을 컨트롤 방향 기준으로 변환
	moveDirection = FTransform(GetControlRotation()).TransformVector(moveDirection);

	/*
	//플레이어 이동 - 등속운동
	FVector P0 = GetActorLocation(); //현재위치
	FVector vt = moveDirection * moveSpeed * DeltaTime; //이동거리
	FVector P = P0 + vt;
	SetActorLocation(P);
	*/

	AddMovementInput(moveDirection);
	//방향 초기화
	moveDirection = FVector::ZeroVector; //ZeroVector; == FVector(0,0,0)
}

void ATPSPlayer::FireCoolTimer(float Duration, float deltaTime)
{
	if (fireTimerTime < Duration)
	{
		fireTimerTime += deltaTime;
	}
	else
	{
		fireTimerTime = 0;
		fireReady = true;
	}
}

void ATPSPlayer::SpawnBullet()
{
	FTransform firePostion = weaponMeshComp->GetSocketTransform(TEXT("FirePostion"));
	GetWorld()->SpawnActor<APBullet>(magazine, firePostion);
}

void ATPSPlayer::ShowFX()
{
	if (niagaraFX == nullptr)
	{
		niagaraFX = GetComponentByClass<UNiagaraComponent>();
	}

	bool show = GetCharacterMovement()->IsFalling();
	//niagaraFX->SetVisibility(show);
	GetMesh()->SetVisibility(!show);
}

'언리얼엔진 > ThirdPersonTemplete' 카테고리의 다른 글

스폰한 캐릭터 안움직이는 이유  (0) 2023.12.04
AnimNotify  (0) 2023.11.16
언리얼 Animation Montage  (0) 2023.11.14
캐릭터 메시 지정하기  (0) 2023.11.13
PBullet 발사체 만들기  (1) 2023.11.13