본문 바로가기

Unreal Engine 4/C++

<Unreal C++> 55 - Action RPG (Fist Mode)

 

필요한 개념


<Fist(주먹) Mode>
Fist는 충돌체만 있으면 됨
-> 충돌체의 이름, 컴포넌트 이름을 소켓 이름으로 만들어 관리를 편하게 제작한다.
충돌체를 4개(왼주먹, 오른주먹, 왼다리, 오른다리)를 만든다.

* BP_CAttachment_Fist 세팅

 

* 충돌체 설정

 


* BeginPlay할때 GetComponentByClass() SphereComponent로 제한해주고, 자식인 4개의 충돌체를 가져오고, 반복문으로 충돌체를 얘의 이름(소켓명)을 가져와서 Character의 Mesh에 붙여줌

* BP_CAttachment_Fist 이벤트 그래프

 



* CAttachment에서 이에 맞게 AttachToCollision() 정의

void ACAttachment::AttachTo(FName InSoketName)
{
	// 얘는 자기 자신을 통째로 붙임
	AttachToComponent(OwnerCharacter->GetMesh(), FAttachmentTransformRules(EAttachmentRule::KeepRelative, true), InSoketName);
}


void ACAttachment::AttachToCollision(UShapeComponent* InComponent, FName InSoketName)
{
	// 얘는 컴포넌트 하나만 붙임
	InComponent->AttachToComponent(OwnerCharacter->GetMesh(), FAttachmentTransformRules(EAttachmentRule::KeepRelative, true), InSoketName);
}


* 3개 Action Montage 세팅
FullBody로 해주고, 나머지 노티파이 세팅해준다.

 

1)

 

 

 

 

2)

 

 

 

 

3, 4)

Section을 2개를 만들어서 처리했다.(Default, Next)

-> 즉, 한 개 몽타주 안에 2개의 액션 공격이 있는 것임


3번 몽타주는 트릭, 동작들을 끊어야 한다.(발로 차고 주먹으로 공격이니까, 콤보로 끊어서 사용)
주먹부분 발 부분을 Section으로 나눠서 처리(Section 전에 BeginAction으로 현재 몽타주 정지 다음 몽타주 넘어가고, EndAction으로 몽타주 정지시키면 된다.)

-> Begin_DoAction에서 다음 동작으로 넘어가게 되면 StopMontage를 이용해 현재 몽타주를 정지시킴
End_DoAction()에 StopMontage가 있는 이유는 동작이 없으면 끊어져야 하고(하고 나서 특정부분에서 중단 시켜야 함)
Begin_DoAction()에 StopMontage가 있는 이유는 다음껄 연결하기 위해서 중단을 시킴


* BeginAction을 EndAction 좀 앞에 둬야한다.(안그러면 프레임 수 딸려서 다음동작으로 안넘어감)
-> 다음동작 안나옴
또한 EndAction이 StartSection보다 살짝이라도 앞에 있어야 정상적으로 작동(몽타주 중지될 수도 있다.)


* DA_Fist 세팅
얘는 Equip 애니메이션이 없다. 없어도 됨, 우리가 else의 경우 End_Equip()하도록 처리를 했었음
1,2,3,4 몽타주 세팅
3는 3번 몽타주 Fist로 하고
4는 3번 몽타주 Fist로 하되, StartSection은 우리가 설정한 Next으로 설정함

 

*&nbsp;DA_Fist




* BP_CPlayer ActionComponent에 DA_Fist 세팅


* CActionComponent에서 FistMode 추가

 

// CActionComponent.h

UENUM(BlueprintType)
enum class EActionType: uint8
{
	Unarmed, Fist, OneHand, TwoHand, Max,
};




* CPlayer에서 입력하면 FistMode로 바꾸는거 세팅

// CPlayer.cpp

PlayerInputComponent->BindAction("Fist", EInputEvent::IE_Pressed, this, &ACPlayer::OnFist);

 

void ACPlayer::OnFist()
{
	CheckFalse(State->IsIdleMode());

	Action->SetFistMode();
}

 

 


* ABP_CPlayer AnimBP에 기본 움직임 동작 세팅(FistMode가 되었을때 기본 동작)

 

* ABP_CPlayer AnimGraph

 

 

CPlayer.h 수정된 내용


더보기
...

UCLASS()
class UONLINE_04_ACTION_API ACPlayer : public ACharacter, public IICharacter
{
	GENERATED_BODY()
	...
    
private:
	void OnFist();
};

 

 

 

 

 

 

 

CPlayer.cpp 수정된 내용


더보기
...

void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	...
	PlayerInputComponent->BindAction("Fist", EInputEvent::IE_Pressed, this, &ACPlayer::OnFist);
}


void ACPlayer::OnFist()
{
	CheckFalse(State->IsIdleMode());

	Action->SetFistMode();
}

 

 

CAttachment.h 수정된 내용


더보기
...

UCLASS()
class UONLINE_04_ACTION_API ACAttachment : public AActor
{
	GENERATED_BODY()

	...
    
protected:
	UPROPERTY(BlueprintReadOnly, VisibleDefaultsOnly)
		class USceneComponent* Scene;

protected:
	// BP에서 접근할 수 있도록
	// 붙일 소켓이름을 받아서 캐릭터 Mesh에 붙여버림
	UFUNCTION(BlueprintCallable)
		void AttachTo(FName InSoketName);

	UFUNCTION(BlueprintCallable)
		void AttachToCollision(class UShapeComponent* InComponent, FName InSoketName);
};

 

 

 

 

 

 

 

CAttachment.cpp 수정된 내용


더보기
...

void ACAttachment::AttachTo(FName InSoketName)
{
	// 얘는 자기 자신을 통째로 붙임
	AttachToComponent(OwnerCharacter->GetMesh(), FAttachmentTransformRules(EAttachmentRule::KeepRelative, true), InSoketName);
}


void ACAttachment::AttachToCollision(UShapeComponent* InComponent, FName InSoketName)
{
	// 얘는 컴포넌트 하나만 붙임
	InComponent->AttachToComponent(OwnerCharacter->GetMesh(), FAttachmentTransformRules(EAttachmentRule::KeepRelative, true), InSoketName);
}

 

 

CActionComponent.h 추가된 내용


더보기
...

UENUM(BlueprintType)
enum class EActionType: uint8
{
	Unarmed, Fist, OneHand, TwoHand, Warp, Max,
};


UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class UONLINE_04_ACTION_API UCActionComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintPure)
		FORCEINLINE bool IsFistMode() { return Type == EActionType::Fist; }

public:	
	...
	void SetFistMode();

public:
	// 현재 타입의 DoAction 실행
	void DoAction();
};

 

 

 

 

 

 

 

CActionComponent.cpp 추가된 내용


더보기
...

void UCActionComponent::SetFistMode()
{
	SetMode(EActionType::Fist);
}

 

 

 

 

결과