작성
·
47
·
수정됨
0
안녕하세요. 이득우 선생님. 늘 좋은 강의 감사드립니다.
다름이 아니라 제가 저만의 프로젝트를 제작하며 해당 강의를 복습중에 이해가 안되는 부분이있어서, 하루종일 헤메다가 질문드립니다...ㅠㅠ
현재 ABAComboAttack
의 Data중 EffectiveFrameCount
으로 설정한 프레임 이전에 입력이 발생하면, 해당 시점에 Montage_JumpToSection
으로 다음 섹션으로 넘겨주는 구조로 이해했습니다.
다만 궁금한 점은, 수업 예제에서 첫 번째 콤보 공격 애니메이션의 총 프레임, 즉 애니메이션 전체 길이에 해당하는 프레임이 44프레임인것으로 보이는데, (사진 참조)
제가 이해한것을 바탕으로 생각했을때는, 첫 번째 EffectiveFrameCount
는 44이하이기만 하면 상관없다고 생각했고, 약간의 계산 오차를 생각했을때도, 적어도 40이하에서는 안전하게 동작할것이라 예상했습니다.
하지만 예상과 달리 36이상의 값 부터는 문제가 됐습니다. 아무리 연타를 해도 두 번째 콤보 공격이 등장하지 않습니다.
해당 부분 로그를 찍어 디버깅 해보니, Montage_JumpToSection
함수 내부의 GetActiveInstanceForMontage
라는 함수에서 인자로 받아온 몽타주가 현재 실행중인 몽타주 인스턴스 목록, 즉 ActiveMontagesMap
내부에 존재하는지 찾고, 존재하면 해당 섹션으로 이동하도록 되어있는데, 이 부분에서 계속 찾지 못하고 있었습니다.
결론적으로, 1번 섹션이 끝나기 이전에 이미 ActiveMontagesMap
에서는 몽타주 인스턴스가 사라져 있었습니다.
이것이 첫 번째 콤보 공격 애니메이션인 WarriorAttack1 에서 EffectiveFrameCount
값이 35이하 일 때는 Montage_JumpToSection
호출 시점에 존재하고 있고, 36이상의 값에서는 존재하지 않는것이 문제였습니다.
혹시나, 계산 문제일 수도 있겠다 생각하여
void AABCharacterBase::SetComboCheckTimer()
{
int32 ComboIndex = CurrentCombo - 1;
ensure(ComboActionData->EffectiveFrameCount.IsValidIndex(ComboIndex));
const float AttackSpeedRate = 1.0f;
float ComboEffectiveTime = (ComboActionData->EffectiveFrameCount[ComboIndex] / ComboActionData->FrameRate) / AttackSpeedRate;
/*Test Code*/
float SectionStart = ComboActionMontage->CompositeSections[ComboIndex].GetTime();
int NextIndex = FMath::Clamp(ComboIndex + 1, 0, ComboActionData->MaxComboCount - 1);
float SectionNext = ComboActionMontage->CompositeSections[NextIndex].GetTime();
float Length = SectionNext - SectionStart;
/*************/
UE_LOG(LogTemp, Warning, TEXT("Section Length : %f, EffectiveTime : %f"), Length, ComboEffectiveTime);
if (ComboEffectiveTime > 0.0f)
{
GetWorld()->GetTimerManager().SetTimer(ComboTimerHandle, this, &AABCharacterBase::ComboCheck, ComboEffectiveTime, false);
}
}
void AABCharacterBase::ComboCheck()
{
ComboTimerHandle.Invalidate();
if (HasNextComboCommand)
{
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
CurrentCombo = FMath::Clamp(CurrentCombo + 1, 1, ComboActionData->MaxComboCount);
FName NextSection = *FString::Printf(TEXT("%s%d"), *ComboActionData->MontageSectionNamePrefix, CurrentCombo);
/*Test Code*/
if(AnimInstance->Montage_IsPlaying(ComboActionMontage))
{
UE_LOG(LogTemp, Warning, TEXT("Montage Is Playing"));
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Montage Not Playing"));
}
/*************/
AnimInstance->Montage_JumpToSection(NextSection, ComboActionMontage);
SetComboCheckTimer();
HasNextComboCommand = false;
}
}
위와 같이 테스트 코드를 넣어서 로그도 점검해 봤지만,
계산에는 이상이 없는것으로 보였습니다....
서론이 너무 길었는데, 제가 궁금한점은 몽타주가 종료되지 않았음에도 불구하고 ActiveMontagesMap
에서 몽타주 인스턴스가 삭제될 수 있는건지, 만약 그럴 수 있다면 현재 상황에서는 왜 삭제되는것인지 궁금합니다.
긴글 읽어주셔서 감사합니다.
답변 2
0
몽타주가 BlendOut을 시작할 때 몽타주 인스턴스는 활성화 기록에서 제거됩니다.
BlendOut의 기본값은 0.25이므로 36프레임시점에서는 활성화 기록에서 제거됐을 것 같습니다.
0
안녕하세요, 인프런 AI 인턴입니다.
dhqks6님께서 질문해주신 애니메이션 몽타주 문제에 대해 답변해 드리겠습니다.
현재 dhqks6님이 겪고 계신 문제는 Montage_JumpToSection
호출 전에 ActiveMontagesMap
에서 몽타주 인스턴스가 사라지는 상황으로 보입니다. 이는 몽타주가 완료되거나 중지되어 ActiveMontagesMap
에서 제거되는 경우 발생할 수 있습니다. 그러나 문제의 근본 원인은 애니메이션 재생 중 콤보가 중단됨에 따라 몽타주 인스턴스가 적절한 시점에서 비활성화되는 경우입니다.
문제 해결을 위한 몇 가지 체크 포인트:
1. Montage 종료 조건 확인: Montage_SetEndDelegate
를 통해 몽타주가 종료되는 시점에 특정 로직이 삽입되지 않았는지 확인해 주시기 바랍니다. 이는 몰트셋 종료 후 인스턴스를 비활성화할 수 있습니다.
Frame Rate와 Effective Frame Count 설정 확인: 특정 프레임 이상에서 문제가 생기는 경우는 프레임 계산에 대한 오차가 누적되면서 발생할 수 있습니다. 각 애니메이션의 총 프레임과 ‘효과적인’ 프레임 카운트가 Montage_JumpToSection
을 호출하기 전에 몽타주가 여전히 유효한지 확인하세요.
타이머 설정과 타이밍 조절: SetComboCheckTimer()
함수에서 설정된 타이머가 적절한 순간에 콤보 공격을 확인하는 것이 중요한데, 이때 회피될 수 있는 상황을 조사해 보시기 바랍니다.
ComboEffectiveTime
계산으로 인해 발생하는 미세한 타이밍 이슈는 라그가 발생할 수 있으므로, 정확히 맞지 않는다면 오차를 줄이기 위해 EffectiveFrameCount
를 미세 조정해 보세요.관련 토픽에 대해 다음의 이전 답변도 도움이 될 수 있습니다:
- 컴보 입력 타이밍 계산 공식에 포함되는 계수 질문
위 링크에 대한 imagery):
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
BlendOut에 대해 공부해보겠습니다. 답변 감사합니다!