언리얼 학습 노트 17 - C++ 위임(유니캐스트)

I. 소개

        저는 "에이전트"보다 "위임"이라는 용어를 선호합니다. 언리얼 위임은 세 가지 범주, 즉 유니캐스트, 멀티캐스트, 동적 멀티캐스트로 나뉩니다. 이름에서 알 수 있듯이 유니캐스트는 한 번에 하나의 함수의 대리자만 바인딩할 수 있고, 멀티캐스트는 한 번에 여러 함수의 대리자를 바인딩할 수 있으며, 동적 멀티캐스트는 청사진에서 동적으로 바인딩할 수 있으며 여러 함수를 바인딩할 수 있습니다.

        사용된 Unreal 버전은 5.2.1이고 VS 버전은 2022입니다.

2. 실현

        Unreal에서 Actor 클래스를 생성하고 이름을 "DelegateActor" 클래스로 지정합니다.

 1. 유형 정의

유니캐스트는 매개변수로 반환값, 매개변수+반환값의 세 가지 유형의 위임을 정의할 수 있으며, 아래 코드와 같이 이 세 가지 유형의 유니캐스트 위임이 각각 정의되어 있습니다. 모든 지침은 주석 섹션을 참조하세요.

DECLARE_DELEGATE(NoParamDelegate);//没有参数没有返回值的委托,委托名称为“NoParamDelegate”
DECLARE_DELEGATE_OneParam(OneParamDelegate, FString);//一个参数没有返回值的委托,名称为“OneParamDelegate”
DECLARE_DELEGATE_TwoParams(TwoParamDelegate, FString, int32);//两个参数没有返回值的委托,名称为“TwoParamDelegate”
DECLARE_DELEGATE_RetVal(FString, OnlyRetDelegate);//仅仅是返回值的委托,名称为“OnlyRetDelegate”
DECLARE_DELEGATE_RetVal_OneParam(FString, RetOneParamDelegate, FString);//定义了带参数和返回值的委托,第一个参数为返回值,第二个为委托名称,第三个为返回值
2. 대리자 유형 변수 선언

위의 정의는 타입 정의라고 볼 수 있는데, 실제로 사용하려면 아래와 같이 클래스에 이 타입의 변수를 선언해야 합니다.

	//单播代理变量的声明
	NoParamDelegate NoParamDelegate;
	OneParamDelegate OneParamDelegate;
	TwoParamDelegate TwoParamDelegate;
	OnlyRetDelegate OnlyRetDelegate;
	RetOneParamDelegate RetOneParamDelegate;

참고: C++에서는 실제로 변수 이름이 대리자 이름과 동일하도록 허용합니다. 이로 인해 발생하는 문제는 나중에 동일한 유형의 대리자 변수를 정의하려는 경우 오류가 보고된다는 것입니다. 그림 2.1.1과 같이

그림 2.1.1
따라서 변수 이름을 유형 이름과 동일하게 정의하지 않는 것이 좋습니다.
	NoParamDelegate NoParamDelegate1;
	NoParamDelegate NoParamDelegate2;
	OneParamDelegate OneParamDelegate1;
	TwoParamDelegate TwoParamDelegate1;
	OnlyRetDelegate OnlyRetDelegate1;
3. 대리자를 바인딩해야 하는 함수를 정의합니다.

        정의된 함수에는 해당 대리자와 동일한 반환 값과 매개 변수가 있어야 합니다.

	//单播代理绑定函数定义
	void NoParamDelegateFunc1();
	void NoParamDelegateFunc2();
	void OneParamDelegateFunc(FString strVal);
	void TwoParamDelegateFunc(FString strVal, int32 intVal);
	FString OnlyRetDelegateFunc();
	FString RetOneParamDelegateFunc(FString strVal);

구현 코드는 다음과 같습니다. 참고: FString을 반환 값으로 사용하는 경우 선언된 FString 유형 변수 tempStr을 직접 반환할 수 없으며, FString(tempStr)과 같은 구조체를 반환해야 합니다.


void ADelegateActor::NoParamDelegateFunc1()
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, FString::Printf(TEXT("NoParamDelegateFunc1")));
}

void ADelegateActor::NoParamDelegateFunc2()
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, FString::Printf(TEXT("NoParamDelegateFunc2")));
}

void ADelegateActor::OneParamDelegateFunc(FString strVal)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, FString::Printf(TEXT("OneParamDelegateFunc:%s"), *strVal));
}

void ADelegateActor::TwoParamDelegateFunc(FString strVal, int32 intVal)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, FString::Printf(TEXT("NoParamDelegateFunc:%s,%d"), *strVal, intVal));
}
FString ADelegateActor::OnlyRetDelegateFunc()
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, FString::Printf(TEXT("OnlyRetDelegate")));
	return FString();
}

FString ADelegateActor::RetOneParamDelegateFunc(FString strVal)
{
	FString tempStr = strVal.Append("RetOneParamDelegateFunc");
	return FString(tempStr);
}
4. 마지막으로 생성자 또는 기타 초기 함수에 바인딩합니다.

            유니캐스트 델리게이트의 바인딩은 다음과 같습니다.

	NoParamDelegate1.BindUObject(this, &ADelegateActor::NoParamDelegateFunc1);
	NoParamDelegate2.BindUObject(this, &ADelegateActor::NoParamDelegateFunc2);
	OneParamDelegate1.BindUObject(this, &ADelegateActor::OneParamDelegateFunc);
	TwoParamDelegate1.BindUObject(this, &ADelegateActor::TwoParamDelegateFunc);
	OnlyRetDelegate1.BindUObject(this, &ADelegateActor::OnlyRetDelegateFunc);
	RetOneParamDelegate1.BindUObject(this, &ADelegateActor::RetOneParamDelegateFunc);
5. 실행

        다음 코드를 실행하고, 컴파일된 코드가 통과된 후 에디터에서 이 클래스의 블루프린트를 생성하고 장면에 드래그 앤 드롭하여 실행하면 각 함수의 인쇄된 메시지를 확인할 수 있습니다.

	NoParamDelegate1.ExecuteIfBound();
	NoParamDelegate2.ExecuteIfBound();
	OneParamDelegate1.ExecuteIfBound("TestStr");
	TwoParamDelegate1.ExecuteIfBound("TwoParam", 22222);
	OnlyRetDelegate1.Execute();//这个和上面的不一样
	FString tempStr = RetOneParamDelegate1.Execute("this is:");
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, tempStr);

참고: 반환 값이 있는 실행 함수와 반환 값이 없는 실행 함수는 다릅니다. 공식 문서에는 이에 대해 자세히 설명되어 있지 않습니다. 이 실행 함수는 코드를 입력할 때 메시지를 표시하지 않으므로 약간 혼란스럽습니다.

6. 새로운 기능 바인딩 해제 및 바인딩

        언바인딩이 좀 까다롭습니다. 공식 문서에는 "UnBind"라고 되어 있지만 실제로는 "Unbind()" 기능입니다. 토마토 어시스턴트를 사용할 때 프롬프트가 없습니다. "UnBind"를 입력한 후 계속 오류를 보고합니다.

	NoParamDelegate.Unbind();

새로운 함수를 바인딩하려면 이전과 같이 직접 바인딩을 추가하면 바인딩 후에는 이전 함수를 덮어쓰게 되며, 실행 중에는 새로 바인딩된 함수만 실행됩니다.

	NoParamDelegate.BindUObject(this, &ADelegateActor::NoParamDelegateFunc2);

그림 6.1.1은 기타 공식적인 바인딩 기능을 보여주고 있으나 공식적인 사례 설명은 없으며 그림과 같이 간단한 소개 설명만 있을 뿐이다. 이는 Unity와 비교할 수 없기 때문에 각 바인딩마다 직접 할 수 밖에 없다. 그것을 시험해보십시오.

그림 6.1.1

1) 바인드

        기존 델리게이트 객체를 바인딩하면 그런 기능이 없다고 뜨는데, 아직 어떻게 사용하는지 모르겠습니다.

2)바인드스태틱

        정적 함수를 정의한 후 바인딩해야 하며 실행 방법은 변경되지 않습니다.

//定义
static void StaticNoParamDelegate();

//实现
void StaticNoParamDelegate()
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, FString::Printf(TEXT("BindStatic")));
}
//绑定全局静态函数
NoParamDelegate1.BindStatic(StaticNoParamDelegate);

//绑定类中的静态函数
NoParamDelegate1.BindStatic(类名::静态函数名称);

참고: 클래스와 전역 정적 함수를 바인딩할 수 있습니다. 이전 BindUObject와의 차이점은 매개변수 앞에 "&" 연산자가 없다는 것입니다.

3) 바인딩 원시

       바인딩은 Unreal UObject 클래스를 상속하는 함수가 아니며, 이는 BindUObject와 정반대입니다. 먼저 아무것도 상속받지 않는 클래스를 Unreal에서 생성해야 합니다.

그런 다음 매개변수 없이 함수를 추가하고 해당 클래스에 값을 반환합니다. 

//函数定义
	void Raw_NoParamDelegateFunc();

//函数实现
void MyRawClass::Raw_NoParamDelegateFunc()
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, FString::Printf(TEXT("Raw_NoParamDelegateFunc")));
}

참고: Unreal Engine의 화면 인쇄 기능은 일반 Unreal 기본 클래스가 아닌 다른 클래스에서도 사용할 수 있습니다.

이 함수를 바인딩하세요

	MyRawClass* tempRawClass = new MyRawClass();
	NoParamDelegate1.BindRaw(tempRawClass, &MyRawClass::Raw_NoParamDelegateFunc);

바인딩의 첫 번째 매개변수는 객체 포인터입니다. 아래와 같이 객체를 생성하는 또 다른 방법이 있습니다(이것은 C++의 기초입니다(;'༎ຶД༎ຶ`). 

	MyRawClass tempRawClass;
	NoParamDelegate1.BindRaw(&tempRawClass, &MyRawClass::Raw_NoParamDelegateFunc);

4) 바인드람다

Lambda 표현식을 바인딩합니다. Lambda 표현식은 익명 함수 조각입니다. 즉, 함수 내에서 별도의 함수를 정의할 수 있습니다. 코드는 다음과 같습니다. 키워드 auto를 사용하면 "auto LambdaDelegateFunc = []()->void ",( ), 매개변수를 추가할 수 있으며, 반환값을 void 형식에서 다른 반환값 형식으로 변경할 수 있습니다.

	auto LambdaDelegateFunc = []()->void
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("LambdaDelegateFunc")));
		};

	NoParamDelegate1.BindLambda(LambdaDelegateFunc);

바인딩할 메소드 매개변수에 람다 표현식을 직접 작성할 수도 있는데, 이는 위보다 간단하고 함수 이름이 전혀 없습니다.

	NoParamDelegate1.BindLambda(
		[]()->void
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("LambdaDelegateFunc")));
		}
	);

5)바인드SP

        SharedPtr(스마트 포인터)이 객체를 가리키는 함수, 즉 순수 C++ 클래스(언리얼 기본 클래스에서 상속되지 않은)의 함수를 바인딩합니다. 순수 C++ 클래스는 일반적으로 TSharedPtr을 사용하여 메모리를 관리하기 때문입니다.

	//绑定智指针
	TSharedRef<MyRawClass> ObjSP1 = MakeShareable(new MyRawClass());
	NoParamDelegate1.BindSP(ObjSP1, &MyRawClass::Raw_NoParamDelegateFunc);

이 바인딩 함수는 이전 함수처럼 생성자에 배치하면 안 됩니다. 그렇지 않으면 바인딩이 실패합니다.

6) BindUObject

       바인딩은 Unreal Engine 기본 클래스의 클래스 멤버 함수를 상속하며, 사용법은 이전 사례에서 소개했으므로 다시 설명하지 않습니다. 

3. 요약

3.1 유니캐스트는 매개변수, 반환값, 매개변수+반환값 등 세 가지 유형의 위임을 정의할 수 있습니다.

3.2 대리자를 선언할 때 유형 이름과 동일한 변수 이름을 사용하지 않는 것이 가장 좋습니다.

3.3 바인딩할 함수와 정의된 대리자의 매개변수 및 반환값은 일관성이 있어야 합니다.

3.4 반환 값이 있는 실행 함수와 반환 값이 없는 실행 함수가 다릅니다.

3.5 바인딩 해제는 "UnBind"가 아니라 실제로는 "Unbind()" 함수입니다.

Guess you like

Origin blog.csdn.net/zhangxiao13627093203/article/details/135009106