본문 바로가기

Unreal Engine 4/C++

<Unreal C++> 7 - Material

필요한 개념


<게임 내 에셋을 불러올때>
ConstructorHelpers : 생성자에서만 사용가능(얘가 더 빠름, 기본적으로 얘 사용)
StaticLoadObject : 게임상에서 언제든지 사용가능(동적로딩(게임에서 실시간으로 불러들이는 것) 가능)

게임모두 다 로드된 후에 갑자기 어떤 물체를 띄운다던가 이럴수가 있다. 이럴때는 (StaticLoadObject)
MaterialInstanceConstant를 BeginPlay()에서 StaticLoadObject()를 통해 불러오고 그 상황에서 Dynamic으로 만들기 위해 UMaterialInstanceDynamic::Create() 함수 사용

델리게이션에 의해 콜되는 함수는 전부 UFUNCTION()이 붙음

Tip) 테스트시
독립형 게임은 별도의 프로세스로 실행되므로 게임 프로세스가 죽으나, 에디터 상의 선택된 뷰포트 실행 중에 터지면 에디터 자체가 닫힘
터지면 CrashError가 나오거나, Saved/Log에 나옴(독립형은 로그가 따로 파일로 저장됨)
에디터가 터지면 다시 켜야해서 불편하고 속도 터짐

 

 

* C02_SpawnActor.cpp 참고 이미지

UKismetSystemLibrary::K2_SetTimer() 함수 설명

 

UKismetMathLibrary::RandomFloatInRange() 함수 설명
Material->SetVectorParameterValue() 함수 설명

 

 

 

 

 

C02_SpawnActor.h 추가된 내용


더보기
UCLASS()
class UONLINE_03_CPP_API AC02_SpawnActor : public AActor
{
	GENERATED_BODY()
    
...

private:
	// 델리게이션에 의해 콜되는 함수는 전부 UFUNCTION()이 붙음
	// UKismetSystemLibrary::K2_SetTimer()도 델리게이션에 의해 콜됨 ->  함수 안에서 FTimerDynamicDelegate Delegate;
	UFUNCTION()
		void ChangeColor();

private:
	// Dyanmic Material을 저장할 애
	class UMaterialInstanceDynamic* Material;
}

 

 

 

 

 

 

 

C02_SpawnActor.cpp 추가된 내용


더보기
...
#include "Materials/MaterialInstanceConstant.h"
#include "Materials/MaterialInstanceDynamic.h"

void AC02_SpawnActor::BeginPlay()
{
	Super::BeginPlay();

	// 생성자에서 만들어서 클래스 타입지정해서 여기서 해도 되지만, 잘 그러지 않음
	// MaterialInstanceConstant'/Game/Materials/M_Mesh_Inst.M_Mesh_Inst'
	// MaterialInstanceConstant : 매터리얼 인스턴스라고 생각하면 된다, 에디터 BP에서만 수정가능
	// BP : MaterialInstance -> C++ : UMaterialInstantConstant

	// CHelpers::GetAsset을 쓸려고 하면 안된다.
	// ConstructorHelpers는 생성자에서만 사용 가능, 동적로딩(게임에서 실시간으로 불러들이는 것)에서는 사용불가
	// ConstructorHelpers : 생성자에서만 사용가능하며 에디터 상에서 미리 에셋을 불러놓기 위해 사용
	// StaticLoadObject : 게임상에서 동적으로 에셋을 로딩하기 위해 사용(생성자 사용 불가)
	
	
	// 1: UClass(TSubClassOf로 받을 수 있다.) 부를려는 타입(리플렉션)
	// 모든 UClass로 상속받은애들은 StaticClass()함수가 있다. 자기의 클래스 타입을 리턴시킴
	// 2 : UObject* InOuter : 나중에 레퍼런스 참고해서 보면 된다, 상황에 따라 바뀜(NULL or this)
	// 3 : TCHAR* Name : 경로명(복사한 레퍼런스 경로)
	// 생성된 자료형을 UObject로 리턴해준다.
	// UObject : 쓸 수 있는 최상위의 자료형(즉 캐스팅 해서 써야함)
	//UObject* obj = StaticLoadObject(UMaterialInstanceConstant::StaticClass(), NULL, L"MaterialInstanceConstant'/Game/Materials/M_Mesh_Inst.M_Mesh_Inst'");
	// BP에서 쓰던 타입 캐스팅 할때 Cast이다.
	// Cast<바꿀 변수타입> : 캐스팅 실패시 NULL이 나옴
	//UMaterialInstanceConstant* material = Cast<UMaterialInstanceConstant>(obj);

	UMaterialInstanceConstant* material; // 언리얼 에서는 NULL을 안줘도 기본 초기화가됨(쓰레기값 방지)
	CHelpers::GetAssetDynamic<UMaterialInstanceConstant>(&material, "MaterialInstanceConstant'/Game/Materials/M_Mesh_Inst.M_Mesh_Inst'");

	// material 불른 것을 Dynamic으로 만듬
	// 게임에서 사용할 수 있도록 Dynamic으로
	// UMaterialInstanceDynamic::Create를 이용해 다이나믹 매터리얼을 생성함
	// Material 전체는 UMaterialiInterface로 부터 상속 받아 구현되어 있다.
	Material = UMaterialInstanceDynamic::Create(material, this);
	// Mesh에 우리가 만든 Material 할당함
	Mesh->SetMaterial(0, Material);

	// K2_SetTimer -> Set Timer by Event, by Function 과 동일한걸 사용
	// UFUNCTION(BlueprintCallable, meta=(DisplayName = "Set Timer by Function Name", ScriptName = "SetTimer", DefaultToSelf = "Object", AdvancedDisplay="InitialStartDelay, InitialStartDelayVariance"), Category="Utilities|Time")
	//	static FTimerHandle K2_SetTimer(UObject * Object, FString FunctionName, float Time, bool bLooping, float InitialStartDelay = 0.f, float InitialStartDelayVariance = 0.f);
	// 정의로 가보면 저런데, BlueprintCallable : 블루프린트에서 콜할 수 있고, DisplayName으로 Blueprint에서 나타남
	// 즉 BP에서 SetTimerByFunctionName()과 동일한 함수
	// SetTimerByFunctionName()를 BP에서 콜하면 이 함수가 콜이됨
	// BP의 Self는 C++의 this와 같음
	// 1. 어느 클래스에 있는 함수를 콜할거냐
	// 2. 어떤 함수 이름이냐 콜할 애가
	// 3. 몇초마다 실행할거냐
	// 4. 반복 할거냐
	UKismetSystemLibrary::K2_SetTimer(this, "ChangeColor", 1.0f, true);
}

void AC02_SpawnActor::ChangeColor()
{
	// DynamicMaterial이니까 우리가 값을 임의대로 바꿀 수 있다.
	// BP와 다르게 C에서는 F가 붙음
	// BP에서 Random Float in Range()에다가 툴팁을 보면 해당하는 헤더 위치가 나옴
	FLinearColor color;
	// RandomFloatInRange 애도 BP와 똑같은 함수
	// min, max
	//UFUNCTION(BlueprintPure, Category = "Math|Random", meta = (NotBlueprintThreadSafe))
	//	static float RandomFloatInRange(float Min, float Max);
	// 얘도 정의 보면 똑같다. 그리고 Category는 BP에서 어디에 소속되어있는지 나온다.
	// 즉 얘는 Math->Random 카테고리에 있다고 BP에 쓸때 나옴
	color.R = UKismetMathLibrary::RandomFloatInRange(0, 1);
	color.G = UKismetMathLibrary::RandomFloatInRange(0, 1);
	color.B = UKismetMathLibrary::RandomFloatInRange(0, 1);
	color.A;

	// BP랑 같음
	// Color : 메터리얼 만들때 변수를 Color라함
	Material->SetVectorParameterValue("Color", color);
}

 

 

 

 

 

Global.h 추가된 내용


더보기
...

// Kismet : 언리얼3 스크립트 시스템
// 그래서 Kismet붙으면 블루프린트용이라고 생각하면됨
#include "Kismet/KismetMathLibrary.h" // Random Float in Range() 사용 위해
#include "Kismet/KismetSystemLibrary.h" // SetTimer() 사용 위해

...

 

 

CHelpers.h 추가된 내용


더보기
class UONLINE_03_CPP_API CHelpers
{
  ...
public:
	// 동적로딩
	template<typename T>
	static void GetAssetDynamic(T** OutObject, FString InPath)
	{
		T* obj = Cast<T>(StaticLoadObject(T::StaticClass(), NULL, *InPath));
		// NULL체크를 하면 되는데(asset != NULL)
		// 언리얼에서는 !!두개를 쓴다.
		// !! : null이 아니면 true가 나옴, null이면 false가 나옴
		verifyf(!!obj, L"!!asset");

		*OutObject = obj;
	}
}

 

 

 

 

 

 

 

결과


UKismetSystemLibrary::K2_SetTimer() 함수로 초마다 ChangeColor() 함수를 콜하고 있다.

 

'Unreal Engine 4 > C++' 카테고리의 다른 글

<Unreal C++> 9 - PlayerInputComponent  (0) 2022.04.04
<Unreal C++> 8 - Player  (0) 2022.04.04
<Unreal C++> 4 - Actor Spawn  (0) 2022.04.04
<Unreal C++> 2 - C++과 BP 통신  (0) 2022.03.30
<Unreal C++> 1 - 언리얼 설명 및 환경 구축  (0) 2022.03.30