초보 코린이의 성장 일지
UE4 SubAction Warp 본문
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 |