본문 바로가기
포트폴리오 제작/Project_P

Project_P 캐릭터에 구현된 Move함수 실행시 GameplayTag 부여

by k99812 2024. 10. 4.

Move 함수

캐릭터를 움직이는 Move 기능을 GA가 아닌 캐릭터에 함수로 구현 하였음

그래서 Move가 실행 중일때 Tag를 붙이고 싶으면 따로 코드로 구현해야 함

 

Move 함수를 GA로 구현하지 않은 이유는 GA 실행시 변수를 전달할 방법을 찾지 못함

 

MoveInputReleased

Move 입력이 끝나면 호출되는 함수

Move함수에서 부착한 Tag와 발동중인 Sprint GA가 있으면 취소시키는 함수

 

코드로 Tag 부착

void APPGASCharacterPlayer::Move(const FInputActionValue& Value)
{
	//ASC에 태그 달기
	//#include "GameplayTagContainer.h" 추가
	FGameplayTagContainer WalkingTagContainer;
	WalkingTagContainer.AddTag(PPTAG_CHARACTER_ISWALKING);

	if (GetCharacterMovement()->GetMovementName() == TEXT("Walking"))
	{
		if (!ASC->HasAnyMatchingGameplayTags(WalkingTagContainer))
		{
			ASC->AddLooseGameplayTags(WalkingTagContainer);

			//#include "AbilitySystemGlobals.h" 추가
			if (UAbilitySystemGlobals::Get().ShouldReplicateActivationOwnedTags())
			{
				ASC->AddReplicatedLooseGameplayTags(WalkingTagContainer);
			}
		}
	}
    
    if (GetCharacterMovement()->GetMovementName() != TEXT("Walking"))
	{
		RemoveWalkingTag(WalkingTagContainer);
	}
}

 

  • FGameplayTagContainer WalkingTagContainer;
    WalkingTagContainer.AddTag(PPTAG_CHARACTER_ISWALKING);
    • 태그를 달기 위해서는 GameplayTagContainer에 캐릭터에 추가할 태그를 GameplayTagContainer에 넣어 줘야함
    • #include "GameplayTagContainer.h" 추가
    • PPTAG_CHARACTER_ISWALKING 매크로는 별도로 추가한 매크로
      • 매크로 내용 : FGameplayTag::RequestGameplayTag(FName("Character.State.IsWalking"))
      • 태그를 찾아오는 매크로
  • if (GetCharacterMovement()->GetMovementName() == TEXT("Walking"))
    • 캐릭터 무브먼트 모드가 Walking 이면
    • if (!ASC->HasAnyMatchingGameplayTags(WalkingTagContainer))
      • ASC에 WalkingTagContainer에 들어있는 태그가 없으면
      • ASC->AddLooseGameplayTags(WalkingTagContainer);
        • 태그 추가
      • //#include "AbilitySystemGlobals.h" 추가
        if (UAbilitySystemGlobals::Get().ShouldReplicateActivationOwnedTags())
        {
        ASC->AddReplicatedLooseGameplayTags(WalkingTagContainer);
        }
        • 태그가 추가된걸 리플리케이트 해주는 코드
  • if (GetCharacterMovement()->GetMovementName() != TEXT("Walking"))
    • 캐릭터 무브먼트가 Walking이 아니면
    • RemoveWalkingTag(WalkingTagContainer);
      • RemoveTag 함수 실행

 

코드로 Tag 제거

void APPGASCharacterPlayer::RemoveWalkingTag(const FGameplayTagContainer& RemoveTagContainer)
{
	// ASC에 태그 제거
	if (ASC->HasAnyMatchingGameplayTags(RemoveTagContainer))
	{
		ASC->RemoveLooseGameplayTags(RemoveTagContainer);

		if (UAbilitySystemGlobals::Get().ShouldReplicateActivationOwnedTags())
		{
			ASC->RemoveReplicatedLooseGameplayTags(RemoveTagContainer);
		}
	}
}

 

  • if (ASC->HasAnyMatchingGameplayTags(RemoveTagContainer))
    • ASC에 제거할 태그가 있으면
    • ASC->RemoveLooseGameplayTags(RemoveTagContainer);
      • 태그 제거
    • if (UAbilitySystemGlobals::Get().ShouldReplicateActivationOwnedTags())
      {
      ASC->RemoveReplicatedLooseGameplayTags(RemoveTagContainer);
      }
      • 리플리케이트가 필요한 경우 추가

 

특정 태그가 달린 GA 취소

const FGameplayTagContainer* CancelAbilityTags = new FGameplayTagContainer(PPTAG_ABILITY_ATTACK);
ASC->CancelAbilities(CancelAbilityTags);

 

  • 공격이 진행 중일때 이동을 하면 공격을 취소 시킴
  • const FGameplayTagContainer* CancelAbilityTags = new FGameplayTagContainer(PPTAG_ABILITY_ATTACK);
    • 공격 GA의 태그를 컨테이너에 추가하여 컨테이너를 생성
  • ASC->CancelAbilities(CancelAbilityTags);
    • 컨테이너를 이용하여 어빌리티 취소

 

어빌리티 스펙을 이용하여 GA 취소

FGameplayAbilitySpec* Spec = ASC->FindAbilitySpecFromInputID((int32)EInputAbility::Sprint);
if (Spec->IsActive())
{
	ASC->CancelAbilityHandle(Spec->Handle);
}

 

  • FGameplayAbilitySpec* Spec = ASC->FindAbilitySpecFromInputID((int32)EInputAbility::Sprint);
    • FindAbilitySpec 함수를 통해 어빌리티 스펙을 찾음
  • if (Spec->IsActive())
    • 찾은 스펙이 실행 중이면
    • ASC->CancelAbilityHandle(Spec->Handle);
      • CancelAbilityHandle 함수를 통해 GA 취소

 

전체 코드

void APPGASCharacterPlayer::Move(const FInputActionValue& Value)
{
	//ASC에 태그 달기
	//#include "GameplayTagContainer.h" 추가
	FGameplayTagContainer WalkingTagContainer;
	WalkingTagContainer.AddTag(PPTAG_CHARACTER_ISWALKING);

	if (GetCharacterMovement()->GetMovementName() == TEXT("Walking"))
	{
		if (!ASC->HasAnyMatchingGameplayTags(WalkingTagContainer))
		{
			ASC->AddLooseGameplayTags(WalkingTagContainer);

			//#include "AbilitySystemGlobals.h" 추가
			if (UAbilitySystemGlobals::Get().ShouldReplicateActivationOwnedTags())
			{
				ASC->AddReplicatedLooseGameplayTags(WalkingTagContainer);
			}
		}

		//이동시 공격 어빌리티 캔슬
		const FGameplayTagContainer* CancelAbilityTags = new FGameplayTagContainer(PPTAG_ABILITY_ATTACK);
		ASC->CancelAbilities(CancelAbilityTags);

		//X는 좌우 Y는 상하 입력
		FVector2D MovementVector = Value.Get<FVector2D>();

		//CameraArm->bUsePawnControlRotation = true; 설정을 통해
		//카메라 암과 컨트롤러의 로테이션은 동기화 됨
		//const FRotator Rotation = Controller->GetControlRotation();
		const FRotator Rotation = CameraArm->GetDesiredRotation();
		const FRotator YawRotation(0, Rotation.Yaw, 0);

		const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
		const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

		AddMovementInput(ForwardDirection, MovementVector.Y);
		AddMovementInput(RightDirection, MovementVector.X);
	}

	if (GetCharacterMovement()->GetMovementName() != TEXT("Walking"))
	{
		RemoveWalkingTag(WalkingTagContainer);
	}
	
}

void APPGASCharacterPlayer::MoveInputReleased()
{
	FGameplayTagContainer WalkingTagContainer;
	WalkingTagContainer.AddTag(PPTAG_CHARACTER_ISWALKING);

	InputReleasedDelegate.Execute();
	RemoveWalkingTag(WalkingTagContainer);

	FGameplayAbilitySpec* Spec = ASC->FindAbilitySpecFromInputID((int32)EInputAbility::Sprint);
	if (Spec->IsActive())
	{
		ASC->CancelAbilityHandle(Spec->Handle);
	}
}

void APPGASCharacterPlayer::RemoveWalkingTag(const FGameplayTagContainer& RemoveTagContainer)
{
	// ASC에 태그 제거
	if (ASC->HasAnyMatchingGameplayTags(RemoveTagContainer))
	{
		ASC->RemoveLooseGameplayTags(RemoveTagContainer);

		if (UAbilitySystemGlobals::Get().ShouldReplicateActivationOwnedTags())
		{
			ASC->RemoveReplicatedLooseGameplayTags(RemoveTagContainer);
		}
	}
}