언리얼엔진5/[Part1] 이득우의 언리얼 프로그래밍
[이득우의 언리얼 프로그래밍 Part1 필기] 9. 설계 : 델리게이트
Rocketbabydolls
2024. 2. 19. 17:03
강한 결합
- 클래스들이 서로 의존성을 가지는 경우.
- 이전에 예시에서 사용한 Card를 Person이 가지고 있다고 가정했을 때, Card가 없는 경우 Person이 만들어질 수 없다.
- 이때 Person은 Card 에 대한 의존성을 가진다고 한다.
느슨한 결합
- 실물에 의존하지 말고 추상적 설계에 의존하라.(DIP 원칙)
- Person 이 Card 가 필요한 이유는 출입 확인 때문
- 출입에 관련된 추상적인 설계에 의존하면 ICheck 를 상속받은 카드 인터페이스를 선언해서 해결
- 유지 보수를 쉽게 만들어 준다.
※ DIP원칙 : 의존 역전 원칙 - DIP (Dependency Inversion Principle) DIP 원칙이란 객체에서 어떤 Class를 참조해서 사용해야하는 상황이 생긴다면, 그 Class를 직접 참조하는 것이 아니라 그 대상의 상위 요소(추상 클래스 or 인터페이스)로 참조하라는 원칙이다.
발행 구독 디자인 패턴
언리얼 델리게이트 선언시 고려사항
어떤 데이터를 전달하고 받을 것인가? 인자의 수와 각각의 타입을 설계
- 몇 개의 인자를 전달할 것인가?
- 어떤 방식으로 전달할 것인가?
- 일대일로 전달 / 일대다로 전달
프로그래밍 환경 설정
- C++ 프로그래밍에서만 사용할 것인가?
- UFUCNTION으로 지정된 블루프린트 함수와 사용할 것인가?
어떤 함수와 연결할 것인가?
- 클래스 외부에 설계된 C++ 함수와 연결
- 전역에 설계된 정적 함수와 연결
- 언리얼 오브젝트의 멤버 함수와 연결 (대부분의 경우 이 방식을 사용)
DECLARE_{델리게이트유형}DELEGATE{함수정보}
DECLARE_DELEGATE
- 일대일 형태로 C++ 만 지원
DECLARE_MULTICAST
- 일대다 형태로 C++만 지원
DECLARE_DYNAMIC
- 일대일 형태로 블루프린트를 지원
DECLARE_DYNAMIC_MULTICAST
- 일대다 형태로 블루프린트 지원
인자가 있을 때는 마지막에 Params 수를 지정해준다. (최대 9개)
CourseInfo.h
#CourseInfo.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "CourseInfo.generated.h"
DECLARE_MULTICAST_DELEGATE_TwoParams(FCourseInfoOnChangedSignature, const FString&, const FString&); # 델리게이트 이름 지정과 인자 지정
/**
*
*/
UCLASS()
class UNREALDELEGATE_API UCourseInfo : public UObject
{
GENERATED_BODY()
public:
UCourseInfo();
FCourseInfoOnChangedSignature OnChanged; # 멤버 변수로 델리게이트 선언
void ChangeCourseInfo(const FString& InSchoolName, const FString& InNewContents); # 인자를 맞춰 함수 지정 (연결은 추후)
private:
FString Contents;
};
CourseInfo.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "CourseInfo.h"
UCourseInfo::UCourseInfo()
{
Contents = TEXT("기존 학사 정보");
}
void UCourseInfo::ChangeCourseInfo(const FString& InSchoolName, const FString& InNewContents)
{
Contents = InNewContents;
UE_LOG(LogTemp, Log, TEXT("[CourseInfo] 학사 정보가 변경되어 알림을 발송합니다."));
OnChanged.Broadcast(InSchoolName, Contents); # 연결된 함수에 전부 브로드캐스팅
}
Student.h
UCLASS()
class UNREALDELEGATE_API UStudent : public UPerson, public ILessonInterface
{
GENERATED_BODY()
public:
UStudent();
virtual void DoLesson() override;
void GetNotification(const FString& School, const FString& NewCourseInfo);
};
Student.cpp
void UStudent::GetNotification(const FString& School, const FString& NewCourseInfo)
{
UE_LOG(LogTemp, Log, TEXT("[Student] %s님이 %s로부터 받은 메시지 : %s"), *Name, *School, *NewCourseInfo);
}
MyGameInstance.h
UCLASS()
class UNREALDELEGATE_API UMyGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
UMyGameInstance();
virtual void Init() override;
private:
UPROPERTY()
TObjectPtr<class UCourseInfo> CourseInfo; # 포인터로 전방선언
UPROPERTY()
FString SchoolName;
};
MyGameInstance.cpp
// 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"
#include "CourseInfo.h"
UMyGameInstance::UMyGameInstance()
{
SchoolName = TEXT("학교");
}
void UMyGameInstance::Init()
{
Super::Init();
CourseInfo = NewObject<UCourseInfo>(this); # 실행중에 학사정보를 계속 유지할 것이기 때문에 Outer 는 this
UE_LOG(LogTemp, Log, TEXT("============================"));
UStudent* Student1 = NewObject<UStudent>();
Student1->SetName(TEXT("학생1"));
UStudent* Student2 = NewObject<UStudent>();
Student2->SetName(TEXT("학생2"));
UStudent* Student3 = NewObject<UStudent>();
Student3->SetName(TEXT("학생3"));
CourseInfo->OnChanged.AddUObject(Student1, &UStudent::GetNotification); # 클래스 멤버 함수를 레퍼런스로 지정 (델리게이트 연결 완료)
CourseInfo->OnChanged.AddUObject(Student2, &UStudent::GetNotification);
CourseInfo->OnChanged.AddUObject(Student3, &UStudent::GetNotification);
CourseInfo->ChangeCourseInfo(SchoolName, TEXT("변경된 학사 정보"));
UE_LOG(LogTemp, Log, TEXT("============================"));
}
UStudent* Student1 = NewObject<UStudent>();
Student1->SetName(TEXT("학생1"));
UStudent* Student2 = NewObject<UStudent>();
Student2->SetName(TEXT("학생2"));
UStudent* Student3 = NewObject<UStudent>();
Student3->SetName(TEXT("학생3"));
이렇게 선언한 오브젝트들은 더 이상 참조되지 않을 때 가비지 컬렉터가 Destroy 한다.
오브젝트
기본적인 게임플레이 요소인 액터와 오브젝트에 대한 설명입니다.
docs.unrealengine.com