초보 코린이의 성장 일지

UE4 SubAction Warp 본문

언리얼

UE4 SubAction Warp

코오린이 2023. 6. 29. 16:03

Decal을 사용하여 Warp 스킬을 구현해 볼 것이다.

1. Sword를 복사해서 Warp로 이름을 변경해준다.

1. 충돌체 등 다 필요하지 않으므로, 삭제하고 Decal를 추가해준다.

2. 바닥을 향하도록 Y축을 -90도 해준다.

1. Warp를 선택해서 넣어주고, 나머지는 구현 후 다시 넣어줄 것이다.

 

1. Weapon을 선택하고, Warp를 추가해준다.


#include "Characters/CPlayer.h"
#include "Global.h"
#include "CAnimInstance.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "Components/InputComponent.h"
#include "Components/CWeaponComponent.h"
#include "Components/CMontagesComponent.h"
#include "Components/CMovementComponent.h"

void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAction("Warp", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetWarpMode);

}

1. Player로가서 Warp 버튼을 추가해준다.


1. 장착, 해제에 노드를 연결해준다.

1. Player 자리 바로 밑에 Decal이 나오는걸 확인할 수 있다.


#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Weapons/CWeaponStructures.h"
#include "CDoAction.generated.h"

UCLASS(Abstract) // 객체화 되면 안되므로 Abstract
class U2212_06_API UCDoAction : public UObject
{
	GENERATED_BODY()
	
public:
	UCDoAction(); // 생성자
    
	virtual void Tick(float InDeltaTime) {}

};

1. DoAction에가서 Warp에 사용할 Tick을 생성해준다.

#include "Components/CWeaponComponent.h"
#include "Global.h"
#include "CStateComponent.h"
#include "GameFramework/Character.h"
#include "Weapons/CWeaponAsset.h"
#include "Weapons/CAttachment.h"
#include "Weapons/CEquipment.h"
#include "Weapons/CDoAction.h"
#include "Weapons/CSubAction.h"

void UCWeaponComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// SubAction 있다면 콜해주기.
	if (!!GetDoAction())
		GetDoAction()->Tick(DeltaTime);

	// SubAction 있다면 콜해주기.
	if (!!GetSubAction())
		GetSubAction()->Tick(DeltaTime);
}

1. WeaponComponent로가서 Tick에 DoAction을 추가해준다.


 

 

 

1. DoAction을 상속받아서 클래스를 생성해준다.

#pragma once

#include "CoreMinimal.h"
#include "Weapons/CDoAction.h"
#include "CDoAction_Warp.generated.h"

UCLASS(Blueprintable)
class U2212_06_API UCDoAction_Warp : public UCDoAction
{
	GENERATED_BODY()

public:
    UCDoAction_Warp();

    virtual void BeginPlay
    (
        class ACAttachment* InAttachment,
        class UCEquipment* InEquipment,
        class ACharacter* InOwner,
        const TArray<FDoActionData>& InDoActionData,
        const TArray<FHitData>& InHitData
    );

    void Tick(float InDeltaTime) override;

public:
    void DoAction() override;
    void Begin_DoAction() override;

private:
    // 클릭될 위치 구해서 return 주는 용도
     bool GetCursorLocationAndRotation(FVector& OutLocation, FRotator& OutRotation);

private:
    class APlayerController* PlayerController;
    class UDecalComponent* Decal;

private:
    FVector MoveToLocation;
	
};
#include "Weapons/DoActions/CDoAction_Warp.h"
#include "Global.h"
#include "GameFramework/Character.h"
#include "GameFramework/PlayerController.h"
#include "Components/CStateComponent.h"
#include "Components/DecalComponent.h"
#include "Components/CapsuleComponent.h"
#include "Weapons/CAttachment.h"

UCDoAction_Warp::UCDoAction_Warp()
{

}

void UCDoAction_Warp::BeginPlay(ACAttachment* InAttachment, UCEquipment* InEquipment, ACharacter* InOwner, const TArray<FDoActionData>& InDoActionData, const TArray<FHitData>& InHitData)
{
	Super::BeginPlay(InAttachment, InEquipment, InOwner, InDoActionData, InHitData);

	Decal = CHelpers::GetComponent<UDecalComponent>(InAttachment);
	PlayerController = OwnerCharacter->GetController<APlayerController>();
}

void UCDoAction_Warp::Tick(float InDeltaTime)
{
	Super::Tick(InDeltaTime);

}

void UCDoAction_Warp::DoAction()
{
	CheckFalse(DoActionDatas.Num() > 0);
	CheckFalse(State->IsIdleMode());

	Super::DoAction();

	// 액션 실행
	DoActionDatas[0].DoAction(OwnerCharacter);

}

void UCDoAction_Warp::Begin_DoAction()
{
	Super::Begin_DoAction();

}

bool UCDoAction_Warp::GetCursorLocationAndRotation(FVector& OutLocation, FRotator& OutRotation)
{
	
}

1. 액션동작이 나오는지 먼저 확인해 본다.

1. BP로 생성해준다.

 

1. DoAction Class 선택해주고, 아래에 알맞은 정보들을 선택 및 설정해준다.

1. 사용할 몽타주로 들어가서 노티파이들을 알맞은 자리에 넣어준다.

1. 동작과 파티클이 잘 나오는걸 확인할 수 있다.


#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Weapons/CWeaponStructures.h"
#include "CDoAction.generated.h"

UCLASS(Abstract) // 객체화 되면 안되므로 Abstract
class U2212_06_API UCDoAction : public UObject
{
	GENERATED_BODY()

protected:
	bool bInAction;

}
#include "Weapons/CDoAction.h"
#include "Global.h"
#include "CAttachment.h"
#include "CEquipment.h"
#include "GameFramework/Character.h"
#include "Components/CStateComponent.h"
#include "Components/CMovementComponent.h"

void UCDoAction::DoAction()
{
	bInAction = true;
	// 구조체에있는 DoAction을 직접적으로 콜할게 아니다.
	// 각 각 맞는 상황에서 맞는 동작을 콜하게 될 것이므로, SetActionMode로 처리.
	State->SetActionMode();
}

void UCDoAction::End_DoAction()
{
	bInAction = false;
	bBeginAction = false;

	State->SetIdleMode(); // Idle로 동작 돌려주기

	Movement->Move(); // 정상적으로 움직이게
	Movement->DisableFixedCamera(); // 카메라도 돌려준다.
}

1. 액션 중일때 Decal이 움직이는걸 방지하기 위해 bool 변수를 하나 생성해준다.

2. 액션 들어가면 true, 끝나면 false로 만들어준다.


#pragma once

#include "CoreMinimal.h"
#include "Weapons/CDoAction.h"
#include "CDoAction_Warp.generated.h"

UCLASS(Blueprintable)
class U2212_06_API UCDoAction_Warp : public UCDoAction
{
	GENERATED_BODY()

public:
    UCDoAction_Warp();

    virtual void BeginPlay
    (
        class ACAttachment* InAttachment,
        class UCEquipment* InEquipment,
        class ACharacter* InOwner,
        const TArray<FDoActionData>& InDoActionData,
        const TArray<FHitData>& InHitData
    );

    void Tick(float InDeltaTime) override;

public:
    void DoAction() override;
    void Begin_DoAction() override;

private:
    // 클릭될 위치 구해서 return 주는 용도
     bool GetCursorLocationAndRotation(FVector& OutLocation, FRotator& OutRotation);

private:
    class APlayerController* PlayerController;
    class UDecalComponent* Decal;

private:
    FVector MoveToLocation; // 이동하기 위한 변수
	
};
#include "Weapons/DoActions/CDoAction_Warp.h"
#include "Global.h"
#include "GameFramework/Character.h"
#include "GameFramework/PlayerController.h"
#include "Components/CStateComponent.h"
#include "Components/DecalComponent.h"
#include "Components/CapsuleComponent.h"
#include "Weapons/CAttachment.h"

UCDoAction_Warp::UCDoAction_Warp()
{


}

void UCDoAction_Warp::BeginPlay(ACAttachment* InAttachment, UCEquipment* InEquipment, ACharacter* InOwner, const TArray<FDoActionData>& InDoActionData, const TArray<FHitData>& InHitData)
{
	Super::BeginPlay(InAttachment, InEquipment, InOwner, InDoActionData, InHitData);

	Decal = CHelpers::GetComponent<UDecalComponent>(InAttachment);
	PlayerController = OwnerCharacter->GetController<APlayerController>();

}

void UCDoAction_Warp::Tick(float InDeltaTime)
{
	Super::Tick(InDeltaTime);

	// 위치, 회전 초기화
	FVector location = FVector::ZeroVector;
	FRotator rotation = FRotator::ZeroRotator;

	// false라면 hit가 된게 아님.
	if (GetCursorLocationAndRotation(location, rotation) == false)
	{
		Decal->SetVisibility(false);

		return;
	}

	// 액션중이라면 밑에 수행할 필요가 없으므로, return
	if (bInAction)
		return;

	Decal->SetVisibility(true);

	Decal->SetWorldLocation(location);
	Decal->SetWorldRotation(rotation);

}

void UCDoAction_Warp::DoAction()
{
	CheckFalse(DoActionDatas.Num() > 0);
	CheckFalse(State->IsIdleMode());

	Super::DoAction();

	FRotator rotation;
	if (GetCursorLocationAndRotation(MoveToLocation, rotation)) // MoveToLocation에 기록을 해놓는다.
	{
		// 높이를 보정해 놓지 않으면 땅에 묻히는 버그가 발생하므로, 일정 크기만큼 올려준다.
		float height = OwnerCharacter->GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
		MoveToLocation = FVector(MoveToLocation.X, MoveToLocation.Y, MoveToLocation.Z + height);

		// 이동할 회전 방향에서 Yaw값만 사용.
		float yaw = UKismetMathLibrary::FindLookAtRotation(OwnerCharacter->GetActorLocation(), MoveToLocation).Yaw;
		OwnerCharacter->SetActorRotation(FRotator(0, yaw, 0)); // 회전방향 yaw 돌려주기.

	}
	// 아니라면 끝.
	else
		return;

	// 액션 실행
	DoActionDatas[0].DoAction(OwnerCharacter);

}

void UCDoAction_Warp::Begin_DoAction()
{
	Super::Begin_DoAction();

	OwnerCharacter->SetActorLocation(MoveToLocation); // Warp 이동
	MoveToLocation = FVector::ZeroVector; // 다시 없애준다.
}

bool UCDoAction_Warp::GetCursorLocationAndRotation(FVector& OutLocation, FRotator& OutRotation)
{
	CheckNullResult(PlayerController, false);

	FHitResult hitResult;
	// Hit되고, 보이는걸 전부 추적할 것이므로, Channel을 사용
	PlayerController->GetHitResultUnderCursorByChannel(ETraceTypeQuery::TraceTypeQuery1, false, hitResult);
	CheckFalseResult(hitResult.bBlockingHit, false); // hit가 되질 않았다면 false

	OutLocation = hitResult.Location;
	OutRotation = hitResult.ImpactNormal.Rotation();

	return true; // hit가 됐다면 그대로 return

}

1. Decal로 이동하는 코드를 작성.

2. 액션 중일때 Decal이 움직이지 못하도록, bool변수를 활용하여 막아준다.


https://www.youtube.com/watch?v=gsaeHYKNIHs 

 

'언리얼' 카테고리의 다른 글

UE4 SubAction Around Skill  (0) 2023.07.03
UE4 SubAction Warp, Top View  (0) 2023.06.30
UE4 SubAction Hammer Skill  (0) 2023.06.27
UE4 SubAction Sword Skill Collision, Hammer Init  (0) 2023.06.26
UE4 SubAction Fist, Sword Skill  (0) 2023.06.23
Comments