언리얼4 C++ 멀티플레이 캐릭터 콤보

Intro

  • 멀티플레이 캐릭터 콤보 구현

몽타주 생성

몽타주 섹션

1

4개의 섹션을 나누고 섹션마다 애니메이션을 넣은 몽타주를 생성한다.

노티파이

2

다음 섹션으로 넘어가기위한 NextAttackCheck 노티파이 추가

변수 선언

콤보를 위한 변수 선언

UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = Attack, Meta = (AllowPrivateAccess = true))
bool CanNextCombo;

UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = Attack, Meta = (AllowPrivateAccess = true))
bool IsComboInputOn;

UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = Attack, Meta = (AllowPrivateAccess = true))
int32 CurrentCombo;

UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = Attack, Meta = (AllowPrivateAccess = true))
int32 MaxCombo;

콤보 보조 함수

콤보 시작 함수

void ARaidPlayer::AttackStartComboState()
{
	CanNextCombo = true;
	IsComboInputOn = false;
	CHECK(FMath::IsWithinInclusive<int32>(CurrentCombo, 0, MaxCombo - 1));
	CurrentCombo = FMath::Clamp<int32>(CurrentCombo + 1, 1, MaxCombo);
}

콤보가 이어지면 다시 다음 콤보를 입력 할수있게 변경한다.

콤보 종료 함수

void ARaidPlayer::AttackEndComboState() 
{
	IsComboInputOn = false;
	CanNextCombo = false;
	CurrentCombo = 0;
}

공격 몽타주 종료시 콤보상태를 초기화한다.

공격 함수

void ARaidPlayer::AttackServer_Implementation()
{
	AttackMulticast();
}

bool ARaidPlayer::AttackServer_Validate()
{
	return true;
}

void ARaidPlayer::AttackMulticast_Implementation()
{
	IsInAir = GetCharacterMovement()->IsFalling();
	if (IsInAir) return;

	if (IsAttacking)
	{
		CHECK(FMath::IsWithinInclusive<int32>(CurrentCombo, 1, MaxCombo));
		if (CanNextCombo)
		{
			IsComboInputOn = true;
		}
	}
	else
	{
		CHECK(CurrentCombo == 0);
		AttackStartComboState();
		PlayerAnim->PlayAttackMontage();
		PlayerAnim->JumpToAttackMontageSection(CurrentCombo);
		IsAttacking = true;
	}

}

멀티플레이를 위해 리플리케이션 함수를 사용하며 좌클릭시 호출된다. 이때 첫번째 공격을할때 AttackStartComboState를 통해 콤보를 입력 할수있는 상태가되고 IsAttackingtrue상태가 되어 다시 입력받았을때 IsComboInputOntrue가된다.

콤보 함수

PlayerAnim->OnNextAttackCheck.AddUObject(this, &ARaidPlayer::ComboServer);

OnNextAtackCheck 노티파이가 발생하면 콤보가 이어질것인지 체크하는 Combo 함수가 실행되도록한다.


void ARaidPlayer::ComboServer_Implementation()
{
	ComboMulticast();
}

bool ARaidPlayer::ComboServer_Validate()
{
	return true;
}

void ARaidPlayer::ComboMulticast_Implementation()
{
	CanNextCombo = false;

	if (IsComboInputOn)
	{
		AttackStartComboState();
		PlayerAnim->JumpToAttackMontageSection(CurrentCombo);
	}
}

마찬가지로 콤보가 이어진다면 다른 클라이언트에도 알리도록 리플리케이션해준다.

공격함수에서 한번더 입력이 들어와서 IsComboInputOntrue상태라면 AttackStartComboState을 통해 콤보 섹션을 1더한다음 애님인스턴스에서 JumpToAttackMontageSection 함수를 통해 다음 섹션으로 넘어가도록한다.

AnimInstance 함수

다음 섹션으로 넘어가기위한 함수

void URaidPlayerAnimInstance::JumpToAttackMontageSection(int32 NewSection)
{
	CHECK(Montage_IsPlaying(AttackMontage));
	Montage_JumpToSection(GetAttackMontageSectionName(NewSection), AttackMontage);
}

FName URaidPlayerAnimInstance::GetAttackMontageSectionName(int32 Section)
{
	CHECK(FMath::IsWithinInclusive<int32>(Section, 1, 4), NAME_None);
	return FName(*FString::Printf(TEXT("Attack%d"), Section));
}

GetAttackMontageSectionName 함수를 통해 섹션이름을 리턴받아 그 섹션으로 넘어가도록 하는 함수

정리

3

간단하게 정리하면 NextAttackcheck 노티파이 이전에 추가입력이 들어온다면 NextAttackcheck 노티파이에서 다음 섹션으로 애니메이션이 이어지고 추가입력이 없으면 현재 섹션만 재생하고 초기화된다.

실행 결과

4

참고문서

이득우, 이득우의 언리얼 C++ 게임개발의 정석,2018, 270쪽

댓글남기기