응애맘마조

231213 강의 본문

공부/UE강의

231213 강의

TH.Wert 2023. 12. 13. 20:33

캐릭터를 움직이고 검을 들고 공격하고 3타하는 모션을 만들었습니다.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "C_Character.generated.h"

UENUM(BlueprintType)
enum class EEquipState : uint8
{
	UNARMED = 0,
	SWORD
};

UCLASS()
class SCENEA_API AC_Character : public ACharacter
{
	GENERATED_BODY()
private:
	bool isRotation;
	bool isEquipped;
	bool isMove;

	int  ComboCount;
	float ComboDelayTime;
	float ComboDelay[2] = { 1.0f,2.0f };
	bool  isAttacking;

	class UMaterialInstanceDynamic* Material;

public:

	UPROPERTY(EditDefaultsOnly)
		class USpringArmComponent* SpringArm;

	UPROPERTY(EditDefaultsOnly)
		class UCameraComponent* Camera = nullptr;

	UPROPERTY(EditDefaultsOnly)
		EEquipState EquipState = EEquipState::UNARMED;

	AC_Character();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

	void OnMoveForward(float Axis);
	void OnMoveRight(float Axis);
	void OnRotationYaw(float Axis);
	void OnRotationPitch(float Axis);

	void CamRotationLock();
	void CamRotationUnLock();

	void OnRunning();
	void OnWalking();

	void OnJumpping();

	UFUNCTION(BlueprintCallable)
	void ChangeColor(FLinearColor color);

	void OnAttack();
	void OnSelectSword();

	void EquipSword();
	void EquipedSword();

	void UnEquipSword();
	void UnEquipedSword();

	FORCEINLINE bool GetIsEquipped() { return isEquipped; }
	FORCEINLINE void SetIsMove(bool ismove) { isMove = ismove; }
	FORCEINLINE void SetIsAttacking(bool b) { isAttacking = b; }

	void SetDelayTime();
private:
	class AC_Swrod* Sword;

	class UAnimMontage* _EquipSword;
	class UAnimMontage* _UnEquipSword;
	class UAnimMontage* _SwordAttack;
};
// Fill out your copyright notice in the Description page of Project Settings.

#include "C_Character.h"
#include "Global.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Materials/MaterialInstanceConstant.h"
#include "Animation/AnimMontage.h"
#include "Scene3/C_Swrod.h"

// Sets default values
AC_Character::AC_Character()
{
	ComboCount = 1;
	ComboDelayTime = 0.0f;
	isAttacking = false;

	isRotation = false;
	isEquipped = false;
	isMove = true;
 	// 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;

	//메시 컴포넌트 안에(기존에있던 컴포넌트) 스켈레탈메시 로드해서 붙이기
	USkeletalMesh* mesh;
	CHelpers::GetAsset< USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
	GetMesh()->SetSkeletalMesh(mesh);
	GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
	GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));

	/*SpringArm = CreateDefaultSubobject<USpringArmComponent>("SpringArm");
	SpringArm->SetupAttachment(GetCapsuleComponent());*/

	CHelpers::CreateComponent< USpringArmComponent>(this, &SpringArm, "SpringArm",
		GetCapsuleComponent());

	CHelpers::CreateComponent< UCameraComponent>(this, &Camera, "Camera",
		SpringArm);

	SpringArm->SetRelativeLocation(FVector(-30, 0, 60));
	SpringArm->SetRelativeRotation(FRotator(-30, 0, 0));

	SpringArm->bUsePawnControlRotation = true;

	TSubclassOf<UAnimInstance> animInstance;
	CHelpers::GetClass< UAnimInstance>(&animInstance,
		"AnimBlueprint'/Game/Scene2/BP/ABP_C_Character.ABP_C_Character_C'");
	GetMesh()->SetAnimInstanceClass(animInstance);

	GetCharacterMovement()->MaxWalkSpeed = 300.0f;
	GetCharacterMovement()->JumpZVelocity = 1000.0f;

	CHelpers::GetAsset<UAnimMontage>(&_EquipSword, "AnimMontage'/Game/Character/Animations/OneHand/Draw_Sword_Montage.Draw_Sword_Montage'");
	CHelpers::GetAsset<UAnimMontage>(&_UnEquipSword, "AnimMontage'/Game/Character/Animations/OneHand/Sheath_Sword_Montage.Sheath_Sword_Montage'");
	CHelpers::GetAsset<UAnimMontage>(&_SwordAttack, "AnimMontage'/Game/Character/Animations/OneHand/Sword_Attack_Montage.Sword_Attack_Montage'");
}

// Called when the game starts or when spawned
void AC_Character::BeginPlay()
{
	Super::BeginPlay();
	
	UMaterialInstanceConstant* material;
	CHelpers::GetAssetDynamic<UMaterialInstanceConstant>(&material,
		L"MaterialInstanceConstant'/Game/Character/Materials/M_UE4Man_Body_Inst.M_UE4Man_Body_Inst'");

	Material = UMaterialInstanceDynamic::Create(material, this);
	GetMesh()->SetMaterial(0, Material);

	Sword = AC_Swrod::Spawn(GetWorld(), this);
	Sword->UnEquip();
}

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

	if (ComboDelayTime > 0.0f)
	{
		ComboDelayTime -= DeltaTime;
		if (ComboDelayTime <= 0.0f) ComboCount = 1;
	}
}

// Called to bind functionality to input
void AC_Character::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAxis("MoveForward", this, &AC_Character::OnMoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &AC_Character::OnMoveRight);
	PlayerInputComponent->BindAction("CamRotationLock", EInputEvent::IE_Pressed, this, 
		&AC_Character::CamRotationUnLock);
	PlayerInputComponent->BindAction("CamRotationLock", EInputEvent::IE_Released, this,
		&AC_Character::CamRotationLock);

	PlayerInputComponent->BindAxis("RotationYaw", this, &AC_Character::OnRotationYaw);
	PlayerInputComponent->BindAxis("RotationPitch", this, &AC_Character::OnRotationPitch);

	PlayerInputComponent->BindAction("PressRun", EInputEvent::IE_Pressed, this,
		&AC_Character::OnRunning);
	PlayerInputComponent->BindAction("PressRun", EInputEvent::IE_Released, this,
		&AC_Character::OnWalking);

	PlayerInputComponent->BindAction("Jumping", EInputEvent::IE_Pressed, this,
		&AC_Character::OnJumpping);

	PlayerInputComponent->BindAction("SelectSword", EInputEvent::IE_Pressed, this,
		&AC_Character::OnSelectSword);

	PlayerInputComponent->BindAction("Attack", EInputEvent::IE_Pressed, this,
		&AC_Character::OnAttack);
}

void AC_Character::OnMoveForward(float Axis)
{
	if (!isMove) return;

	FRotator rotator = FRotator(0, GetControlRotation().Yaw, 0);
	FVector dir = FQuat(rotator).GetForwardVector().GetSafeNormal2D();
	AddMovementInput(dir, Axis);
}

void AC_Character::OnMoveRight(float Axis)
{
	if (!isMove) return;

	FRotator rotator = FRotator(0, GetControlRotation().Yaw, 0);
	FVector dir = FQuat(rotator).GetRightVector().GetSafeNormal2D();
	AddMovementInput(dir, Axis);
}

void AC_Character::OnRotationYaw(float Axis)
{
	if(isRotation)
	AddControllerYawInput(Axis);
}

void AC_Character::OnRotationPitch(float Axis)
{
	if (isRotation)
	AddControllerPitchInput(Axis);
}

void AC_Character::CamRotationLock()
{
	isRotation = false;
}

void AC_Character::CamRotationUnLock()
{
	isRotation = true;
}

void AC_Character::OnRunning()
{
	GetCharacterMovement()->MaxWalkSpeed = 1000.0f;
}

void AC_Character::OnWalking()
{
	GetCharacterMovement()->MaxWalkSpeed = 300.0f;
}

void AC_Character::OnJumpping()
{
	Jump();

}

void AC_Character::ChangeColor(FLinearColor color)
{
	Material->SetVectorParameterValue("BodyColor", color);
}

void AC_Character::SetDelayTime()
{
	if (ComboCount == 3)
	{
		ComboDelayTime = 0.0f;
		ComboCount = 1;
	}
	ComboDelayTime = ComboDelay[ComboCount -1];
}

void AC_Character::OnAttack()
{
	if (EquipState == EEquipState::SWORD && !isAttacking)
	{
		if (ComboDelayTime > 0.0f)
		{
			ComboCount++;
			if (ComboCount > 3)
			{
				ComboCount = 1;
				ComboDelayTime = 0.0f;
			}
		}

		FString str = "Attack";
		str.Append(FString::FromInt(ComboCount));
		PlayAnimMontage(_SwordAttack, 1.0f, FName(str));
	}
}

void AC_Character::OnSelectSword()
{
	isEquipped = !isEquipped;

	if (isEquipped)
	{
		EquipState = EEquipState::SWORD;
		PlayAnimMontage(_EquipSword);
	}
	else
	{
		EquipState = EEquipState::UNARMED;
		PlayAnimMontage(_UnEquipSword);
	}
}

void AC_Character::EquipSword()
{
	isMove = false;
	bUseControllerRotationYaw = true;
	GetCharacterMovement()->bOrientRotationToMovement = false;
	GetCharacterMovement()->RotationRate.Yaw = 0.0f;
}

void AC_Character::EquipedSword()
{
	isMove = true;
	Sword->Equip();
}

void AC_Character::UnEquipSword()
{
	isMove = false;
	GetCharacterMovement()->RotationRate.Yaw = 360.0f;
}

void AC_Character::UnEquipedSword()
{
	isMove = true;
	Sword->UnEquip();	
	bUseControllerRotationYaw = false;
	GetCharacterMovement()->bOrientRotationToMovement = true;
}

캐릭터의 움직임 모션을 C++로 언리얼 엔진에서 실행할 수 있게 클래스로 정리했습니다.

실행 영상

읽어주셔서 감사합니다.

'공부 > UE강의' 카테고리의 다른 글

231215 강의  (0) 2023.12.15
231214 강의  (0) 2023.12.14
231212 강의  (0) 2023.12.12
231211 강의  (0) 2023.12.11
231129 강의  (0) 2023.11.30
Comments