일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- MAC
- ret2libc
- 게임 개발
- frequency-domain spectrum analysis
- stride
- CTF
- 운영체제
- Double free
- DSP
- AINCAA
- 유스케이스
- 언리얼엔진
- RBAC
- DP
- Race condition
- STCF
- 메카님
- Unity #Indie Game
- sampling theory
- TSet
- linear difference equation
- MLFQ
- Rr
- pdlc
- 게임개발
- 유니티
- dirty cow
- 배경 그림
- dtft
- Security
- Today
- Total
다양한 기록
[UE] Composition (컴포지션) 본문
Has-a 관계
(상속은 Is-a 관계)
SOLID
Single Responsibility Principle - 하나의 객체는 하나의 의무만 가지도록
Open-Closed Principle - 기존에 구현된 코드를 변경하지 않으면서 새로운 기능 추가 가능하도록
Liskov Substitution Principle - 자식 객체를 부모 객체로 변경해도 작동에 문제 없을 정도로 상속을 단순히
Interface Segregation Design - 객체가 구현해야 할 기능이 많다면 이들을 여러 개의 단순한 인터페이스로 분리하여 설계
Dependency Inversion Principle - 구현된 실물보다 구축해야 할 추상적 개념에 의존
하나의 언리얼 오브젝트는 항상 CDO를 가짐
언리얼 오브젝트 간의 컴포지션?
- CDO에 미리 언리얼 오브젝트를 생성해 조합 (필수적 포함)
- CreateDefaultSubObject()
- CDO에 빈 포인터만 넣고 런타임에서 언리얼 오브젝트를 생성해 조합 (선택적 포함)
- NewObject()
내가 소유한 언리얼 오브젝트 -> 서브오브젝트
나를 소유한 "" -> 아우터
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Card.generated.h"
UENUM()
enum class ECardType : uint8
{
Student = 1 UMETA(DisplayName = "For Student"),
Teacher UMETA(DisplayName = "For Teacher"),
Staff UMETA(DisplayName = "For Staff"),
Invalid
};
/**
*
*/
UCLASS()
class UNREALCOMPOSITION_API UCard : public UObject
{
GENERATED_BODY()
public:
UCard();
FORCEINLINE ECardType GetCardType() const { return CardType; }
FORCEINLINE void SetCardType(ECardType InCardType) { CardType = InCardType; }
private:
UPROPERTY()
ECardType CardType;
UPROPERTY()
uint32 Id;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "Card.h"
UCard::UCard()
{
CardType = ECardType::Invalid;
Id = 0;
}
열거형, 메타데이터까지 지정 가능함
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Person.generated.h"
/**
*
*/
UCLASS()
class UNREALCOMPOSITION_API UPerson : public UObject
{
GENERATED_BODY()
public:
UPerson();
FORCEINLINE const FString& GetName() const { return Name; }
FORCEINLINE void SetName(const FString& InName) { Name = InName; }
FORCEINLINE class UCard* GetCard() const { return Card; }
FORCEINLINE void SetName(class UCard* InCard) { Card = InCard; }
protected:
UPROPERTY()
FString Name;
// UE 4까지의 표준
/*UPROPERTY()
class UCard* Card;*/
// UE5 표준, 구현에서는 포인터 써도 됨
TObjectPtr<class UCard> Card;
private:
};
Person.h 헤더 파일, 객체 선언 시 원시 포인터 형태로 선언은 언리얼4 때까지의 표준
선언은 이제 TObjectPtr로 선언해주는게 좋음
구현에서는 그냥 포인터 써도 됨
위 예제에서는 독립성을 높이기 위해 전방 선언되었음
// Fill out your copyright notice in the Description page of Project Settings.
#include "Person.h"
#include "Card.h"
UPerson::UPerson()
{
Card = CreateDefaultSubobject<UCard>(TEXT("NAME_Card"));
Name = TEXT("홍길동");
}
Person.cpp 파일, CreateDefaultSubObject로 필수 포함 시킴
인자에 FNAME을 넣어서 유니크한 값을 설정해줘야 하는데, 이때 TEXT의 시작을 NAME으로 시작해서
이게 FNAME인지 분간하기 쉽게 함
// Fill out your copyright notice in the Description page of Project Settings.
#include "Staff.h"
#include "Card.h"
UStaff::UStaff()
{
Card->SetCardType(ECardType::Staff);
Name = TEXT("김직원");
}
Staff, Student, Teacher는 각각 카드를 포함함
Person의 생성자에서 이미 카드 오브젝트를 만들긴 하기 때문에 또 만들 필요는 없음
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyGameInstance.h"
#include "Student.h"
#include "Teacher.h"
#include "Staff.h"
#include "Card.h"
UMyGameInstance::UMyGameInstance()
{
SchoolName = TEXT("기본학교");
}
void UMyGameInstance::Init()
{
Super:: Init();
TArray<UPerson*> Persons = { NewObject<UStudent>(), NewObject<UTeacher>(), NewObject<UStaff>() };
UE_LOG(LogTemp, Log, TEXT("=================================="));
for (const auto Person : Persons)
{
const UCard* OwnCard = Person->GetCard();
check(OwnCard);
ECardType CardType = OwnCard->GetCardType();
UE_LOG(LogTemp, Log, TEXT("%s님이 소유한 카드 종류: %d"), *Person->GetName(), CardType);
const UEnum* CardEnumType = FindObject<UEnum>(nullptr, TEXT("/Script/UnrealComposition.ECardType"));
if ( CardEnumType )
{
FString CardMetaData = CardEnumType->GetDisplayNameTextByValue((int64)CardType).ToString();
UE_LOG(LogTemp, Log, TEXT("%s님이 소유한 카드 종류: %s"), *Person->GetName(), *CardMetaData);
}
}
UE_LOG(LogTemp, Log, TEXT("=================================="));
}
게임인스턴스
복잡할만한 건 메타데이터 가져오기
절대 경로를 지정해서 오브젝트를 뽑아아와야 함
/Script/UnrealComposition.ECardType
/Script 밑에 모듈 안에 존재함
CardEnumType->GetDisplayNameTextByValue((int64)CardType).ToString();
이걸 통해 DisplayName을 뽑아올 수 있음
기본 리턴은 FText인데, FString으로 처리해야 로그 출력됨
'언리얼 엔진 > Unreal C++' 카테고리의 다른 글
[UE] Unreal Container Library / TArray, TSet (0) | 2024.12.28 |
---|---|
[UE] Delegate (델리게이트) / 발행 구독 패턴 (0) | 2024.12.26 |
[UE] Interface (인터페이스) (0) | 2024.12.22 |
[UE] 언리얼 오브젝트 리플렉션 시스템 (0) | 2024.12.18 |
[UE] 언리얼 오브젝트 기초 (0) | 2024.12.18 |