해결된 질문
작성
·
94
·
수정됨
0
파트2의 10강 28:50 에서, if 문에
"ABOpponentCharacter->SetLevel(CurrentStageNum);" 구문을 추가로 넣은 후 게임을 진행하면서 다음 두번째 적이 스폰될 때, HpBar가 100/150의 비율로 렌더링이 되는 것이 이해가 잘 가지 않습니다.
"HpProgressBar->SetPercent" 함수가 HpProgressBar의 비율을 계산하여 렌더링 하는것이 맞다면, 적이 스폰될 때 StatComponent에서의 beginplay를 통해 BaseStat.MaxHp 가 100 이 된 후, 위젯의 "SetupCharacterWidget" 이 호출되어 순서대로 "SetMaxHp"를 통해 위젯의 MaxHp 또한 100 이 되고 끝으로 "SetPercent(NewCurrentHp / MaxHp);" 를 실행하여 100/100 비율로 체력바가 올바르게 갱신되어 렌더링되는 것 까지는 이해했습니다.
근데 적 Level이 2가 될 때, 스텟컴포넌트의 BaseStat.MaxHp 가 "28:50"에서 추가했던 "SetLevel(CurrentStageNum);" 으로 인해 150 으로 갱신되고, 문제는 그 이후에 아래와 같은 두 추가적인 과정이 없이 어떻게 게임상에서 보이는 체력바의 비율이 100/150 의 비율로 갱신이 될수 있던 것인지 궁금합니다.
HpBarWidget->SetMaxHp(Stat->GetTotalStat().MaxHp); 구문을 다시 실행시켜서 HpBarWidget 의 MaxHp 변수를 150 으로 갱신시켜주고
OnHpChanged.Broadcast(CurrentHp); 를 명시적으로 호출하여, HpProgressBar->SetPercent(NewCurrentHp / MaxHp); 를 실행시켜서, 갱신이 필요한 CurrentHp의 값인 100과, 1.을 통해 150 으로 갱신된 MaxHp 두 값의 100/150 비율이 비로소 렌더링이 된다.
28:50 코드 이후에
위 두가지 코드를 실행하는 구문이 명시적으로 추가되지 않다면, ABHpBarWidget의 MaxHp는 여전히 100일 것이며, 150으로 갱신되었다 하더라도 여전히 UpdateHpBar를 호출하지 않았으므로 SetPercent(NewCurrentHp/MaxHp)를 호출하지 못하여 100/100의 비율로 렌더링이 되었어야 한다고 생각이 드는데, 실제론 전혀 그렇지 않고 스텟컴포넌트에서 변경된 MaxHp가 위젯의 MaxHp에도 자동으로 적용되어 100/150의 올바른 비율로 갱신되는 이유가 궁금합니다.
log 를 한번 찍어보았는데, 저는 "GetWorld()->SpawnActor" 로 월드에 적이 스폰 된후 InitWidget 을 통해 위젯이 생성된 다음, 곧바로 nativeconstruct 가 호출될 것으로 예상했으나 다음 구문인 "ABOpponentCharacter->SetLevel(CurrentStageNum);" 이 실행되고, 이 구문이 실행이 완료되고 나서야 뒤늦게 위젯의 nativeconstruct 가 실행됩니다. 만약 이 흐름이 버그가 아니라면, 뒤늦게 nativeconstruct가 호출됨으로써
HpBarWidget->SetMaxHp(Stat->GetTotalStat().MaxHp);
HpBarWidget->UpdateHpBar(Stat->GetCurrentHp());
위 두 구문이 실행이 되는 것이므로 지금 보이는 체력바의 모습이 비로소 이해가 됩니다. 근데 이 nativeconstruct 의 호출타이밍이 왜 InitWidget 의 실행이 끝난 후 바로 호출이 되지 않고, 그 다음 구문인
"ABOpponentCharacter->SetLevel(CurrentStageNum);" 이 실행이 끝나고 나서야 호출이 되는 것인지 궁금합니다.
혹시 몰라 해당 프로젝트를 깃허브에 올려놓았습니다.
https://github.com/jaebyoung/MyArenaBattle_2_10
(업로드가 처음이라 제대로 올라간 것인지 모르겠습니다..)
답변 2
0
네 코드는 잘 보입니다.
10강에서는 SpawnActorDeferred 함수를 사용해 BeginPlay 이전에 데이터를 초기화한 후 위젯이 렌더링되도록 구성했습니다.
브레이크포인트 걸어보면 캐릭터가 본격적으로 초기화되기 전에 클래스의 SetLevel 함수가 호출되고, 이후에 InitWidget과 NativeConstruct등이 호출되는 것을 확인할 수 있습니다.
0
안녕하세요, 인프런 AI 인턴입니다. hush park님,
질문해주신 부분은 언리얼 엔진에서 체력바를 비롯한 다른 요소들의 상태 갱신이 어떻게 자동화되어 있을 수 있는지에 대한 좋은 예입니다. 언리얼 엔진 내에서 이벤트와 바인딩을 통한 데이터 처리 및 렌더링 이슈가 어떻게 해결되는지 이해하는 것이 중요합니다.
언리얼 엔진에서는 델리게이트(delegate)와 이벤트 시스템이 이러한 상태 변화를 자동으로 처리할 수 있도록 돕습니다. SetLevel(CurrentStageNum);
함수가 호출될 때 이는 캐릭터의 스탯을 갱신하고, 그에 따라 자연스럽게 관련된 델리게이트 또는 이벤트가 호출될 수 있습니다. 이를 통해 UI, 즉 창을 그리는 위젯이 자동으로 업데이트됩니다.
이벤트 시스템에서는 BaseStat.MaxHp
값이 변경되면 이를 감지하고 필요에 따라 UI 컴포넌트를 갱신하는 역할을 합니다. 다음은 이유를 더 명확히 하기 위한 몇 가지 요점입니다.
델리게이트와 바인딩의 역할: OnHpChanged
와 같은 델리게이트가 이미 정의되어 있다면, 각종 스탯 변경 시 이러한 델리게이트가 자동으로 브로드캐스트될 수 있습니다. 이로 인해 UI는 별도의 직접적인 함수 호출 없이도 자신의 상태를 인식하고 업데이트할 수 있습니다.
자동화된 상태 동기화: UI에서 보여지는 현 상태와 데이터 레이어의 상태가 자동으로 동기화됩니다. ABOpponentCharacter->SetLevel()
호출 시 스탯 데이터가 변하는 즉시 인기 앞선 체계에 따라 변경사항이 즉각적으로 반영됩니다.
아래의 기존 질문과 답변 링크에서도 비슷한 맥락에서 이러한 문제를 다루고 있습니다:
플레이어에만 위젯을 넣었는데 NPC에서 HpBar가 어떻게 나오나요??: 이 링크는 UI원이 변경된 데이터에 반응하는 방법에 대한 토론을 다루고 있습니다.
많이 어려운데, 한개씩 이해하고있는 중이라,질문입니다.: 여기에서는 위젯의 데이터와 UI 상태 관리에 대해 다양한 접근법을 소개하고 있습니다.
이러한 자동화된 시스템은 데이터와 UI의 일치를 유지하는 데에 매우 유용하며, 특히 체력 바와 같은 실시간 업데이트가 필요한 요소에서 발생하는 복잡성을 줄여줍니다. 이러한 델리게이트 구조는 다양한 게임 엔진 및 그래픽 인터페이스에서 광범위하게 사용되고 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.