필요한 개념
블푸는 일반적으로 다른팀에서 사용
프로그램팀에서는 기본값을 지정해주고 다른팀에서 바꿔씀
함수도 마찬가지
이 함수도 어떻게 당신들이 가져다가 내용을 어떻게 정의할지 모릅니다.
그 함수 콜만 하는 것만 넣고
그 정의 내용을 알아서 정의해서 쓰세요
우리는 작성하느 이 함수는 어떤 역할을 할거에요(선언, 정의 다 해놓고 재정의해서 쓰세요)
1. 우리는 어떻게 사용될지 모르니까 알아서 정의하세요(ImplementTable)
2. 우리가 정의했는데 필요하면 재정의해서 쓰세요.(Native)
어떻게 열여주고, 쓰는지 방법을 알아봄
언리얼엔진 내부에서도 이렇게 되어있는 경우도 많고, C에서도 재정의해서 쓰는 경우도 있고
C10_Override.h
protected:
// BP에서 접근 위해
// BlueprintImplementableEvent : C++에서는 정의하지 않고 해당 클래스로부터
// 상속받은 자식에서 정의하거나 BP에서 정의해서 사용(BP든 C든 상속받은 자식에서 정의하는 것이다.)
// C에서 상속받았다면 함수명_Implementation으로 정의가 가능
// 정의 만들기 안해도 컴파일이 됨!(몸체가 없이)
// 왜 가능하냐면? 자식이나, BP에서 재정의 가능해서 컴파일이 된다.
// 몸체가 없는데 콜도 가능
// 재정의 안하면 콜이 무시되고 재정의하면 콜이됨
// C에서 얘를 상속받은 자식에서 재정의하는 것은 Native와 방식이 동일
UFUNCTION(BlueprintImplementableEvent)
void ChangeColorRed();
자식으로 BP를 만들어서 보면
ChangetColorRed 이벤트를 노드로 정의할 수 있다.
protected:
// BlueprintNativeEvent : C++에서 정의를 해놓고 필요에 따라서
// BP에서 재정의를 해서 사용(즉, 몸체가 있어야함)
UFUNCTION(BlueprintNativeEvent)
void ChangeColorWhite();
void ChangeColorWhite_Implementation();
// void ChangeColorWhite_Implementation();
// BlueprintNativeEvent는 C++ 정의할때 _Implementation를 사용
// 자식에서 재정의시 Implementation을 붙여서 기본 기능의 함수를 정의(따로 virtual 안 붙여도됨)
C10_Override.cpp
void AC10_Override::ActorEndOverlap(AActor* OverlappedActor, AActor* OtherActor)
{
// 자식에서 ChangeColorWhite_Implementation로 재정의해도
// ChangeColorWhite() 얘를 호출시켜야 한다.
ChangeColorWhite();
}
결과를 보면 BP에서 Trigger를 나올때(Native) C에서 기본적으로 정의한 파란색은 무시되고 BP에서 재정의한 하얀색이 되는 것을 알 수 있다.
정리하자면
ImplementTable은 콜은 해주는데 알아서 몸체를 만들라
Native은 기본으로 정의했는데 필요하면 재정의하라는 것임
정리
BlueprintImplementableEvent
- C++에는 선언과 호출부만 존재
- 함수의 정의는 자식에서 수행
- C++에서 상속받았다면 함수명_Implementation 정의로 가능
BlueprintNativeEvent
- C++에는 선언과 호출부, 정의부 존재
- C++에서 정의할때 _Implementation를 사용
- 자식에서 재정의 했다면 C++의 정의부는 무시됨
C10_Override.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "C10_Override.generated.h"
UCLASS()
class UONLINE_03_CPP_API AC10_Override : public AActor
{
GENERATED_BODY()
private:
UPROPERTY(VisibleDefaultsOnly)
class USceneComponent* Scene;
UPROPERTY(VisibleDefaultsOnly)
class UBoxComponent* Box;
UPROPERTY(VisibleDefaultsOnly)
class UTextRenderComponent* Text;
public:
AC10_Override();
protected:
virtual void BeginPlay() override;
protected:
// BP에서 접근 위해
// BlueprintImplementableEvent : C++에서는 정의하지 않고 해당 클래스로부터
// 상속받은 자식에서 정의하거나 BP에서 정의해서 사용
// 정의 만들기 안해도 컴파일이 됨!(몸체가 없이)
// 왜 가능하냐면? 자식이나, BP에서 재정의 가능해서 컴파일이 된다.
// 몸체가 없는데 콜도 가능
// 재정의 안하면 콜이 무시되고 재정의하면 콜이됨
// C에서 얘를 상속받은 자식에서 재정의하는 것은 Native와 방식이 동일
UFUNCTION(BlueprintImplementableEvent)
void ChangeColorRed();
// BlueprintNativeEvent : C++에서 정의를 해놓고 필요에 따라서
// BP에서 재정의를 해서 사용(즉, 몸체가 있어야함)
UFUNCTION(BlueprintNativeEvent)
void ChangeColorWhite();
void ChangeColorWhite_Implementation();
// void ChangeColorWhite_Implementation();
// BlueprintImplementableEvent, BlueprintNativeEvent은 모두
// 자식에서 재정의시 Implementation을 붙여서 기본 기능의 함수를 정의
private:
UFUNCTION()
void ActorBeginOverlap(AActor* OverlappedActor, AActor* OtherActor);
UFUNCTION()
void ActorEndOverlap(AActor* OverlappedActor, AActor* OtherActor);
};
C10_Override.cpp
#include "C10_Override.h"
#include "Global.h"
#include "CPlayer.h"
#include "Components/BoxComponent.h"
#include "Components/TextRenderComponent.h"
AC10_Override::AC10_Override()
{
CHelpers::CreateComponent<USceneComponent>(this, &Scene, "Scene");
CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Scene);
CHelpers::CreateComponent<UTextRenderComponent>(this, &Text, "Text", Scene);
Box->SetRelativeScale3D(FVector(3));
Box->bHiddenInGame = false;
Text->SetRelativeLocation(FVector(0, 0, 100));
Text->SetRelativeRotation(FRotator(0, 180, 0));
Text->SetRelativeScale3D(FVector(2));
Text->TextRenderColor = FColor::Red;
Text->HorizontalAlignment = EHorizTextAligment::EHTA_Center;
Text->Text = FText::FromString(GetName());
}
void AC10_Override::BeginPlay()
{
Super::BeginPlay();
OnActorBeginOverlap.AddDynamic(this, &AC10_Override::ActorBeginOverlap);
OnActorEndOverlap.AddDynamic(this, &AC10_Override::ActorEndOverlap);
}
void AC10_Override::ActorBeginOverlap(AActor* OverlappedActor, AActor* OtherActor)
{
ChangeColorRed();
}
void AC10_Override::ActorEndOverlap(AActor* OverlappedActor, AActor* OtherActor)
{
// 자식에서 ChangeColorWhite_Implementation로 재정의해도
// ChangeColorWhite() 얘를 호출시켜야 한다.
ChangeColorWhite();
}
void AC10_Override::ChangeColorWhite_Implementation()
{
ACPlayer* player = Cast<ACPlayer>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
player->ChangeColor(FLinearColor(0, 0, 1));
}
BP_C10_Override
CPlayer.h 추가된 내용
...
UCLASS()
class UONLINE_03_CPP_API ACPlayer : public ACharacter
{
GENERATED_BODY()
...
public:
// BlueprintCallable : 블루프린트에서 콜 가능하도록
UFUNCTION(BlueprintCallable)
void ChangeColor(FLinearColor InColor);
private:
class UMaterialInstanceDynamic* BodyMaterial;
class UMaterialInstanceDynamic* LogoMaterial;
};
CPlayer.cpp 추가된 내용
...
#include "Materials/MaterialInstanceConstant.h"
#include "Materials/MaterialInstanceDynamic.h"
...
void ACPlayer::BeginPlay()
{
...
UMaterialInstanceConstant* bodyMaterial;
CHelpers::GetAssetDynamic<UMaterialInstanceConstant>(&bodyMaterial, "MaterialInstanceConstant'/Game/Materials/M_UE4Man_Body_Inst.M_UE4Man_Body_Inst'");
UMaterialInstanceConstant* logoMaterial;
CHelpers::GetAssetDynamic<UMaterialInstanceConstant>(&logoMaterial, "MaterialInstanceConstant'/Game/Materials/M_UE4Man_ChestLogo_Inst.M_UE4Man_ChestLogo_Inst'");
BodyMaterial = UMaterialInstanceDynamic::Create(bodyMaterial, this);
LogoMaterial = UMaterialInstanceDynamic::Create(logoMaterial, this);
GetMesh()->SetMaterial(0, BodyMaterial);
GetMesh()->SetMaterial(1, LogoMaterial);
}
void ACPlayer::ChangeColor(FLinearColor InColor)
{
BodyMaterial->SetVectorParameterValue("BodyColor", InColor);
LogoMaterial->SetVectorParameterValue("BodyColor", InColor);
}
결과
'Unreal Engine 4 > C++' 카테고리의 다른 글
<Unreal C++> 22 - SweepTrace (0) | 2022.04.24 |
---|---|
<Unreal C++> 20 - Line Trace / Dynamic Delegate (0) | 2022.04.15 |
<Unreal C++> 18 - Event (0) | 2022.04.15 |
<Unreal C++> 16 - Multicast Delegate (0) | 2022.04.15 |
<Unreal C++> 15 - Delegate (0) | 2022.04.07 |