+ 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!


<종류별로 BP를 만들었을 때의 파일 모양>



UWidget?

Widget에서 사용되는 가장 Base Class.


UUserWidget?

말 그대로, User가 직접 여러 종류의 Widget을 선택 및 관리하여 화면에 보여지는 Widget이다.

즉, 화면에 보여지는 여러 Widget들을 감싸고 있는 것이 UUserWidget이라고 생각해 된다.


UPanelWidget?

여러 Widget들을 배치할 수 있는 Panel로 사용되는 Widget.

배치되는 Widget들을 Child로 생각해, Slots 멤버 변수를 통해 관리한다.

Unity의 UIPanel을 생각하면 될 것 같다.


WidgetTree?

WidgetTree는 말그대로 Widget의 상하관계에 대한 구조를 Tree형태로 관리하는 Class를 말한다.

이 Class를 통해, 부모/자식 Widget의 정보를 확인해서, 원하는 정보를 참조할 수 있다.


- Root Widget

WidgetTree Class 내부에는 RootWidget이라는 멤버변수가 있는데, 이것은 WidgetTree를 가지고 있는 Widget 중에서 가장 상단에 있는 Panel Widget을 가리키고있다.

내부적으로 어떻게 생성되는지 확인해봤는데...

참조를 통해 알게된 사용되는 함수들 중, BlueprintFactory 함수를 보면, FactoryCreateNew(~~~)를 통새 RootWidget을 초기화 시켜주고있다.

이것을 보니, BP에서 작업할 때, CanvasPanel이 없다면 그냥 만들어서 RootWidget으로 넣어버리는 것 같다.

뭔가 더 내부적으로 파들어가고싶은데... 이거 답이 없을 정도로 깊어지고... 엔진 디버깅을 해야하기에 지금은 멈췄다.


아래의 코드는 Children Widget을 찾기 위해 내부적으로 많이 사용되는 함수의 로직이다.


< ForWidgetAndChildren() >


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Search for any named slot with content that we need to dive into.
    if ( INamedSlotInterface* NamedSlotHost = Cast<INamedSlotInterface>(Widget) )
    {
        TArray<FName> SlotNames;
        NamedSlotHost->GetSlotNames(SlotNames);
 
        for ( FName SlotName : SlotNames )
        {
            if ( UWidget* SlotContent = NamedSlotHost->GetContentForSlot(SlotName) )
            {
                Predicate(SlotContent);
 
                ForWidgetAndChildren(SlotContent, Predicate);
            }
        }
    }
 
    // Search standard children.
    if ( UPanelWidget* PanelParent = Cast<UPanelWidget>(Widget) )
    {
        for ( int32 ChildIndex = 0; ChildIndex < PanelParent->GetChildrenCount(); ChildIndex++ )
        {
            if ( UWidget* ChildWidget = PanelParent->GetChildAt(ChildIndex) )
            {
                Predicate(ChildWidget);
 
                ForWidgetAndChildren(ChildWidget, Predicate);
            }
        }
    }
cs


 INamedSlotInterface를 가진 Widget부터 찾고, 그 뒤에 PanelWidget인지 확인해서 widget들을 순회한다.


INamedSlotInterface는... 어디서 사용되는지 찾아봐도 나오지 않는데, 이름을 통해 의도를 생각해보면, Widget Slot을 만들 때, 이걸 Implement해서 사용해라. 그러면 API를 통해 Slot으로 관리하기 편할 것이다. 라는 의미인 듯 싶다.


* WidgetTree를 잘 이용하면, Runtime에 Widget들을 잘 통제할 수 있을 것이다!





Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

 + 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!



기본적인 TSoftClassPtr과 TSubclassOf에 대한 기록


Unreal DataTable에서 BP를 기록하는 과정에서 의문이 들어 조사하게 되었다.


TSoftClassPtr<T>

  • 말 그대로 Class Soft Pointer라는 뜻으로, 해당 값이 가리키는 데이터는 직접 지정한 template형의 데이터일 것.

  • 그리고 그 데이터는 UClass, UE4 엔진이 실행될 때, 처음 생성되어 보관되어지는 Unreal Class Meta Data일 것이다.

  • 만약, 한 번도 생성되지 못한 것이라면, LoadSynchronous()를 통해 해당 CDO(Class Default Object)를 생성해줄 수 있다.

  • Get() Load UClass를 반환한다. CDO를 반환하는 것일 듯.

  • 해당 데이터형을 사용하려면, Get()이나 LoadSynchronous()를 잘 활용해야할 것이다.

 

TSubclassOf<T>

  • 이 데이터형은 Type안정성을 위해서 사용하는 경우가 많다.
    , 값으로 들어오는 클래스 정보는 T를 상속한 Class다 라는 의미를 명확히 할 때, 사용하는 데이터 형이다.

  • 이것도 기본적으로는 내부에 UClass* 데이터를 가지고 있다.

  • 이 클래스의 Get() **this를 반환하는데... 기본적인 operator*연산이 Class포인터를 넘기는 작업이니까,
    **this
    UClass 원본 데이터를 반환하는게 아닐까 싶다.

  • 호환되는 TSubclassOf 유형을 서로에게 할당하는 연산은 RunTime Check하고,
    서로 호환되지 않는 TSubclassOf 유형(공통 부모조차 없는 전혀다른 클래스) CompileTime Check한다.
    왜냐하면, 호환되는 유형은 null 값등이 사용될 수 있지만, 서로 호환되지 않는 유형은 Crash를 유발할 수 있기 때문!

 

T name;

  • 그냥 template형으로, 사용하게되면 CDO와는 다른 인스턴스가 생성되어 메모리에 잡힐 것으로 예상됨.




Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

 + 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!



Unreal 공부를 하면서 FArchiveFVariant에 대해서 알게되었는데, 이 부분에 관한 지식을 찾기위해 구글링을 해 본 결과, 제대로된 지식을 아직 못 얻었다...


뭔가 대충 느낌을 알거같긴한데...


그래서 그냥 개인 메모 형식으로 남겨둔다.


FArchive

Base class for archives that can be used for loading, saving, and garbage collecting in a byte order neutral way.


byte 순서 중립적인 방법(??? 무슨뜻인지 몰라서 직역하긴 했는데... 그냥 byte배열로 사용할 수 있는 건가??)으로 로딩, 저장, GC에 사용할 수 있는 기본 클래스.



FVariant

Implements an extensible union of multiple types.

Variant types can be used to store a range of different built-in types, as well as user defined types. The values are internally serialized into a byte array, which means that only FArchive serializable types are supported at this time.


다양한 타입의 확장 가능한 결합을 구현한다.

Variant타입은 다른 built-in type이나 유저가 정의한 타입 등 다양한 타입을 저장할 때 사용된다.

일반적으로 byte배열로 직렬화되는데, 사용할 수 있는 타입은 FArchive에서 직렬화할 수 있는 타입만 현재 가능하다.


FArchive의 상속 형태 (일부)

FArchive -> FMemoryArchive -> FMemoryWriter, FMemoryReader, FMemoryObject -> ...

... -> FMemoryWriter -> FBufferArchive(TArray를 상속)


FArchive -> FBufferReaderBase -> FBufferReader -> ...

FArchive -> FBufferWriter -> ...

FArchive -> FMemoryArchive -> ...





 + Unreal에서 Binary data를 표현할 때, 기본적으로 uint8의 동적 배열을 사용한다.

각 클래스의 멤버함수 데이터 형을 보면 대부분 uint8 / TArray<uint8>로 되어있는 것을 보면 알 수 있다.



 + FVariant를 사용하는 엔진 코드를 좀 보면, 여러 형태의 데이터를 직렬화해서 함수등으로 전달할 때 사용하고 있다.



 + 여러 자료를 찾아보거나 엔진 코드의 일부분을 봤을 때, 내가 느낀 사용법은,

FVariant FArchive둘 다 직렬화에 사용되는 Class인 것 같고,

FVariant데이터를 주고 받기 위해서 사용한다면,

FArchive데이터 저장, Hard Disk와 주고받기 위해 사용되는 개념인 듯 하다



어우... 진짜 파악하기 힘드네. 대체 어떻게 찾아 공부해야하는거야...? Unreal Docs에 예제 좀 넣어주면 어디 덧나나;;;;; 진짜 불편;;;


 + Unreal Wiki에 Rama라는 사람이 올린 Game Data Save/Load관련 글이 있는데... 이걸 보면 좀 느낌이 더 올지도!

근데 아직 실력이 부족해서 잘 못알아보겠다... 실력을 키우자 ㅠㅠ

 -> https://wiki.unrealengine.com/Save_System,_Read_%26_Write_Any_Data_to_Compressed_Binary_Files



아직 공부가 너무 부족하다... 다른 엔진 코드를 확인하던지해서 공부하자 ㅠㅠ


혹시 잘 아시는 분이 있다면... 알려주시면 감사하겠습니다 ㅠㅠ






Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

+ Recent posts