231129 UnrealLab 발표 들었던 것 정리, 알아보기 힘든 듯

 

0. UObject는 대부분 개체의 최상위 클래스

  • Object 위로 2단계 상속이 있음
    • 1) BaseUtility -> 2) UObjectBase

1. UObjectBase

  • 5개의 멤버변수
    • 1) ObjectFlags : 개체의 여러 상태를 담고 있음
      • RF_MarkAsNative : Cpp에서 정의된
      • RF_ClassDefaultObject : CDO
      • RF_MarkAsRootSet : 가비지 컬렉션 관련
      • RF_NeedInitialization : 공간 -> 생성자 호출 시 ( 초기화가 완료되지 않음 )
    • 2) InternalIndex : 내부 인덱스(?)
      • 생성될 때 하나의 배열에 들어간다 (?)
      • 객체마다 인덱스가 있음
      • 개체 소멸 시 인덱스 재사용
    • 3) ClassPrivate : 클래스 정보
    • 4) NamePrivate : 중복 불가, 모든 개체는 고유한 이름을 가짐
    • 5) OuterPrivate : 개체의 외부 개체(추측)

2. 생성자

  • UObjectBase에 마지막 생성자가 우리가 주로 사용하는 생성자
  • 1) new 사전 작업
    • GUObjectAllocator.AllocateUObjectIndex(,...) : malloc과 같은, 메모리만 할당
  • 2) new
    • void* operator new(size_t size, void* where)의 new 버전을 사용하여 미리 할당받은 공간에 new로 객체 생성
  • 3) CreateDefaultSubobject, NewObject
    • 생성자, 비생성자 차이
  • 4) GUObjectArray ( UObejctHash.cpp 에 정의된 전역 변수, 컨테이너는 아니고 Class, 컨테이너를 내부에 가지고 있는 클래스 )
    • 생성한 개체들이 차곡차곡 쌓인,,배열 ( 앞서 UObjectBase의 InternalIndex에 해당하는 )
    • HashTable vs ObjectArray
      • 4.1) GC(Garbage Collector) : RootSet으로부터 그래프로 뻗어나가는 형태
        • GC로부터 뻗어나온 각 노드가 Array에도 포함되어 있음
      • 4.2) Reachable(도달 가능한) vs Unreachable(도달 불가한)
        • GC는 회수주기(기본값 60초)마다 Unreachable을 마킹(모든 InternalIndex에)
        • Reachable에 해당하는 인덱스를 다시 재마킹 (그래프로부터 깊이 1만큼만 -> Cluster로 묶어서 하위 개체는 검색x (탐색 시간이 오래 걸릴 수 있기 때문) )
        • Cluster 내 루트를 제외한 개체들은 Unreachable 마킹이 되어있지만 Cluster 루트의 Internal Index를 알고 있어 해제처리 되지 않음
        • 이 때 Cluster에 속하는 하위 개체의 바로 앞 부모는 Outer로 추측됨
    • GUObjectArray 내 컨테이너
      • FUObjectItem을 원소로 갖고 있음 ( UObject의 주소 등을 가지는 구조체 )
      • FUObjectItem은 2차원 배열의 형태로 갖고 있음(2중 포인터)
        • Chunk 단위(1차 배열)로 나누어 각 Chunk의 시작 주소를 알고 있게 됨
        • PreAllocateChunks 사용 시 최대 공간 할당 후 각 연속 공간에서 본인 Chunk 크기 만큼을 잘라 시작주소를 가리키게 됨
        • PreAllocateChunks가 true 일 경우가 false일 경우로 나눠 생각하면 됨(연속 공간 vs 필요할 때 마다 할당)
        • GC가 무시하는 영역을 설정할 수 있음(Non_GCable)
      • AllocateUObject 함수 내에서 FUObjectItem에 해당하는 인덱스(IndexToObject 메서드)를 통해 직접 FUobejctItem의 멤버변수를 조정해주는 방식
        • 3가지 분기(재활용, OpenForDisregardForGC, else.. 기본)
      • FreeUObjectIndex 메서드는 FUObjectItem의 값을 바꿔주는 방식 (nullptr로 초기화한다던가)
    • AddObject -> GUObjectAllocator.AllocateUObjectIndex(,...) 를 통해 GC로 관리되게 됨
  • 우리가 사용하지 않는 생성자, EObjectFlags를 인자로 받는 생성자 ( 직접 생성자를 호출하는 방식 ), UClass나 UEnum 그런 것들이 UObject를 상속받기 때문에 걔네 전용이라고 보면 될 듯
    • 형식 정보를 받는(?) 생성자 - 클래스를 안다거나 하는 ?
    • GetClass나 StaticClass나 하는 것은 엔진 시동 시 생성 됨
    • 일단 이 생성자는 아무 것도 안함
    •  
    • 1) DECLARE_CLASS 매크로
      • 이동 생성, 복사 생성 private 처리
      • Super, ThisClass에 대한 typedef
      • StaticClass 포함 ( GetPrivateStaticClass를 내부적으로 호출 -> 선언부만 있음)
      • GetPrivateStaticClass의 반환값이 결국 StaticClass의 반환 값
      • 정의는 어디에 ? -> 다른 매크로
    • 2) IMPLEMENT_CLASS_NO_AUTO_REGISTRATION(TClass) - 3~4번 정도 타고 넘어와야 함 ( GetPrivateStaticClass의 정의부를 찾기 위해 여기까지 옴)
      • 내부적으로 GetPrivateStaticClassBody 함수를 호출 ( 클래스 정보를 핫 리로드, 생성 및 초기화 하는 함수 )
      • 리로드 기능 지원할 경우는 리로드, 아닐 경우 앞서 설명한 대로 new에 대해 공간 미리 할당 받고 그 주소에 대해 UClass의 생성자를 <직접> 호출함
    • 3) 등록 ? -> 2가지에 대해 혼용해서 용어 사용(관리 개체 vs 형식 정보)
      • UObject::Register 메서드 : AddObject에 대한 호출이 없는,, (엔진의 관리 상태로 등록 되지 않음을 뜻함) -> 등록하기 위한 절차가 별도로 필요 ( Register 메서드의 존재 이유 )
      • 내부 등록 vs 외부 등록 (함수 포인터)
      • Registrations.Add ( Registrant )
      • 내부 등록 및 외부 등록을 마친 후 Registrations에 추가한 각 개체에 대해 내부 등록 함수 호출, 외부 등록 함수를 호출함으로서 존재하게 됨

+ Recent posts