인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

hush park님의 프로필 이미지
hush park

작성한 질문수

이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해

10강 게임데이터 관리

28:50 에서 SetPercent 함수와 관련하여 궁금한 점이 있습니다.

해결된 질문

작성

·

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 의 비율로 갱신이 될수 있던 것인지 궁금합니다.

  1. HpBarWidget->SetMaxHp(Stat->GetTotalStat().MaxHp); 구문을 다시 실행시켜서 HpBarWidget 의 MaxHp 변수를 150 으로 갱신시켜주고

  2. 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가 호출됨으로써

  1. HpBarWidget->SetMaxHp(Stat->GetTotalStat().MaxHp);

  2. HpBarWidget->UpdateHpBar(Stat->GetCurrentHp());

     

위 두 구문이 실행이 되는 것이므로 지금 보이는 체력바의 모습이 비로소 이해가 됩니다. 근데 이 nativeconstruct 의 호출타이밍이 왜 InitWidget 의 실행이 끝난 후 바로 호출이 되지 않고, 그 다음 구문인

"ABOpponentCharacter->SetLevel(CurrentStageNum);" 이 실행이 끝나고 나서야 호출이 되는 것인지 궁금합니다.

 

GOMCAM 20241208_2144390415.png.webp

 

GOMCAM 20241207_0719540557.png

 

 

 

 혹시 몰라 해당 프로젝트를 깃허브에 올려놓았습니다.

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 컴포넌트를 갱신하는 역할을 합니다. 다음은 이유를 더 명확히 하기 위한 몇 가지 요점입니다.

  1. 델리게이트와 바인딩의 역할: OnHpChanged와 같은 델리게이트가 이미 정의되어 있다면, 각종 스탯 변경 시 이러한 델리게이트가 자동으로 브로드캐스트될 수 있습니다. 이로 인해 UI는 별도의 직접적인 함수 호출 없이도 자신의 상태를 인식하고 업데이트할 수 있습니다.

  2. 자동화된 상태 동기화: UI에서 보여지는 현 상태와 데이터 레이어의 상태가 자동으로 동기화됩니다. ABOpponentCharacter->SetLevel() 호출 시 스탯 데이터가 변하는 즉시 인기 앞선 체계에 따라 변경사항이 즉각적으로 반영됩니다.

아래의 기존 질문과 답변 링크에서도 비슷한 맥락에서 이러한 문제를 다루고 있습니다:

이러한 자동화된 시스템은 데이터와 UI의 일치를 유지하는 데에 매우 유용하며, 특히 체력 바와 같은 실시간 업데이트가 필요한 요소에서 발생하는 복잡성을 줄여줍니다. 이러한 델리게이트 구조는 다양한 게임 엔진 및 그래픽 인터페이스에서 광범위하게 사용되고 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

hush park님의 프로필 이미지
hush park

작성한 질문수

질문하기