본문 바로가기

Unreal Engine 4/C++

<Unreal C++> 2 - C++과 BP 통신

 

 

필요한 개념

 


컨텐츠 브라우저 내에 C++ 클래스는 프로젝트명/Source와 같다.
컨텐츠 브라우저에는 UObject로 부터 상속 받은 클래스만 나타난다.(ex) 처음 생성하면 GameMode 밖에 안뜬다.)
.cpp는 뜨지 않음(프로그래머가 내부적으로만 사용하니깐) -> 디자이너가 볼때 용이

C01_
C -> 우리가 만든 클래스인지, 언리얼 클래스 인지 구분하기 위해


컨텐츠 브라우저에 C++ 클래스에 간단히 C++ 클래스추가가 가능하다.
추가하면 VisualStudio Game 프로젝트 내에 추가된다.
추가 후 VisualStudio에서 컴파일 하고 컨텐츠 브라우저 C++ 클래스에가면 생성되어 있다.
액터로 생성했다고 가정하면 그 생성 되어있는 것에서 우클릭 -> 기반 블루프린트 생성하면 이 클래스를 기반한 블루프린트 생성이 가능하다.
해당 BP에 들어가면 우 상단에 부모 클래스로 우리 class가 나오게 된다.

Tip) C로 만들고 BP로 만들어야 하느냐?
-> 그렇지는 않다. 액터면 액터 클래스를 직접 화면에 드래그 하면 끌어넣을 수는 있는데 이러면 해당 클래스에 대한 세세한 설정을 할 수 없고, 액터에 어떤 모습이 없어서 화면에
나타나지 않음, 간단히 테스트 할때는 화면에 끌어다 배치하고 아니면 블루프린트로 설정이 필요하다거나 디자이너나 기획팀에서 필요한 내용이 있다면 BP를 만들어서 쓴다.

AActor로부터 상속받은 클래스는 C++ 클래스 자체로도 배치할 수 있지만 세세한 설정을 할 수 없으므로 C++ 클래스 기반의 블루프린트 클래스로 생성해서 배치한다.


우리가 만든 클래스는 액터만 상속 받고 그 기반으로 BP를 만들었고 추가적인 기능을 BP에 넣었다.
기본적인 베이스는, 중요한 로직은 C에서 작업하고 그 기반에서 만들어진 클래스로 BP를 만들어서 다른 팀과 작업을 한다.
우리는 2가지 방식을 다 씀(C로만 배치, C 기반으로 BP로 해서 배치)


확장->확장관리->UnrealMacroGenerator 설치함
Alt + W 키를 누르면 매크로 화면이 나온다.

매크로 설명
UPROPERTY : 변수에다 붙음
UFUNCTION : 함수에다 붙음
UCLASS : 클래스
USTRUCT : 구조체
UENUM : 열거체
UINTERFACE : 인터페이스
UE_LOG : 로그
LOG_CATEGORY : 로그
DELEGATE : 델레게이트 만들때

생성자는 에디터에 관련되어 있으며
BeginPlay는 게임 플레이 코드와 관련되어 있다.
값 초기화는 .h 클래스 내에서 하든, 생성자에서 하든 동일하게 일어남
이니셜라이저(생성자에 : C(30)) 이런것도 똑같음(근데 잘 쓰지는 않음)

클래스에 이렇게 하고

값을 어떻게 공개할지
private:
UPROPERTY(EditAnywhere) // EditAnywhere : 클래스의 기본 값, 배치된 상태에서 수정할 수 있다.(블루프린트에서 눈을 킨다는 거와 동일하다)
int A = 10;
UPROPERTY(EditInstanceOnly) // EditInstanceOnly : 배치된 상태에서 수정할 수 있음(배치된 상태에서만 쓰고 싶을때)
int B = 20;
UPROPERTY(EditDefaultsOnly) // EditDefaultsOnly : 클래스에서 수정 가능(모든 인스턴스들이 공통된 값이 들어가야 할때 쓴다.)
int C;
UPROPERTY(VisibleAnywhere) // VisibleAnywhere : 값을 수정할 수 없고 값의 확인 용도로 사용
int Test = 20; 
결과를 보면

Visible도 범위에 따라 Anywhere, InstanceOnly, DefaultsOnly가 있다.

언리얼에서 BP에서 A,C가 디테일에 나와있다.
그런데 이 액터를 화면에 배치하고 디테일을 보면 A,B가 나온다.

private: -> protected:
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
int Test = 20;

BlueprintReadOnly : 블루프린트에서 읽기 전용으로 접근(블루프린트에서 접근해야 하니까 BP는 상속받은 자식이어서 protected:로 해서 접근 받아야 한다.) 안그럼 에러남
반드시 protected로 설정되어 있어야 컴파일이 완료됨
이렇게 하면 블루프린트에서는 이 변수를 GetTest해서 꺼내서 쓸 수 있지만, 읽기 전용으로 값을 수정할 수 없다.
BlueprintReadWrite : 블루프린트에서 읽고 수정 가능
(BlueprintReadOnly, BlueprintReadWrite든 모두 동일하게 protected: 해야한다. -> 자식 접근해야하니까)


Tip)
C에서 편집했는데 변수값이 바로 적용안된 경우 기본값으로 돌려줘야 한다.

접두사
Actor를 상속 받은애들은 A가 붙고, 
액터가 아닌 UObject로 상속 받은 애들은 U가 붙는다.(액터도 UObject를 상속 받지만 Actor는 예외)
구조체는 F가 붙는다.
근데 간혹 클래스를 가볍게 구조체 처럼 쓸 경우 클래스 접두사로 F를 쓰는 경우가 있다.(FString)
Enum은 E가 붙는다.


FString str;
// Append()는 +=와 동일
str.Append("A :");
// FromInt() : Int형을 문자열로 바꿔줌
str.Append(FString::FromInt(A));
str.Append(", B :");
str.Append(FString::FromInt(B));
str.Append(", C :");
str.Append(FString::FromInt(C));

// 로그를 찍을때 싱글턴 GLog를 사용
GLog->Log(str);

AC02_SpawnActor::AC02_SpawnActor()
{
// 매 프레임마다 Tick을 콜할거냐를 설정
// Tick함수가 없다면 얘도 필요 없다.
  PrimaryActorTick.bCanEverTick = true;
}

4.22까지는 정석은 컴포넌트 변수한테는 VisibleDefaultOnly를 사용하도록 되어있었음
그런데 그 이후 부터는 아무거나 써도 상관없다.

Tip) 헤더 찾는 법은 예를 들어) UStaticMeshComponent라면
구글에 UStaticMeshComponent치면 언리얼 docs에 헤더 위치 및 관련 상속구조가 나온다.

 

UStaticMeshComponent(출처 : UnrealDocs 사이트)


Module : Engine (Module은 라이브러리를 뜻함)
Header : 헤더의 위치(헤더의 위치는 실제 엔진에서의 경로이며, C++ 소스의 헤더추가는 Include의 항목을 사용한다.)

 


Tip)
콘텐츠 브라우저에 뷰 옵션에서 엔진 콘텐츠 표시 누르면 엔진 콘텐츠(Engine/Content/), 엔진 C++ 클래스 폴더(Engine/Source/Editor에서 필요한 부분만 나타남)가 보이게 된다.
엔진 콘텐츠안에 StaterContent가 있다.(4.25에서는 딴데로 옮겨짐)
엔진콘텐츠/BasicShape/에 각종 모양들이 있다.(액터 배치의 모양들)
엔진이 꼬이면 답도 없어서 필요한것은 따로 프로젝트로 옮겨서 사용한다.

요약

Edit/Visible
-AnyWhere
-DefaultsOnly
-InstanceOnly

Blueprint
-ReadOnly
-ReadWrite

 

 

 

 

 

C01_Property.h


더보기
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "C01_Property.generated.h"

UCLASS()
class UONLINE_03_CPP_API AC01_Property : public AActor
{
	GENERATED_BODY()

private:
	UPROPERTY(EditAnywhere)
		int A = 10;
	UPROPERTY(EditInstanceOnly)
		int B = 20;
	UPROPERTY(EditDefaultsOnly)
		int C;

protected:
	UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
		int Test = 20;

public:	
	AC01_Property();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

};

 

 

 

 

 

 

 

C01_Property.cpp


더보기
#include "C01_Property.h"

AC01_Property::AC01_Property()
{
 	PrimaryActorTick.bCanEverTick = true;

	C = 50;
}

void AC01_Property::BeginPlay()
{
	Super::BeginPlay();
	
	FString str;
	// Append()는 +=와 동일
	str.Append("A :");
	// FromInt() : Int형을 문자열로 바꿔줌
	str.Append(FString::FromInt(A));
	str.Append(", B :");
	str.Append(FString::FromInt(B));
	str.Append(", C :");
	str.Append(FString::FromInt(C));

	// 로그를 찍을때 싱글턴 GLog를 사용
	GLog->Log(str);
}

void AC01_Property::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

 

 

C02_SpawnActor.h


더보기
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "C02_SpawnActor.generated.h"

UCLASS()
class UONLINE_03_CPP_API AC02_SpawnActor : public AActor
{
	GENERATED_BODY()

protected:

	// BP에 컴포넌트 추가->StaticMesh가 UStaticMeshComponent이다.
	// U는 UObject에서 상속 받은 애다.(AActor를 거치지 않고 상속 받은 클래스)
	UPROPERTY(VisibleDefaultsOnly)
		class UStaticMeshComponent* Mesh;
	
public:	
	AC02_SpawnActor();

protected:
	virtual void BeginPlay() override;
};

 

 

 

 

 

 

 

C02_SpawnActor.cpp


더보기
#include "C02_SpawnActor.h"
#include "Components/StaticMeshComponent.h"

AC02_SpawnActor::AC02_SpawnActor()
{
	// CreateDefaultSubobject : 실제 생성 함수
	// <어떤 자료형 생성> 1: 컴포넌트이름(변수명과 일치해야 관리편함)
	Mesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
	// BP는 자동으로 SceneComponent라고 Root컴포넌트가 생겨있다.
	// C에서는 지정해줘야 한다.
	// 루트로 쓰겠다.
	RootComponent = Mesh;
}

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

 

 

 

 

 

 

 

UOnline_03_Build.cs


더보기
// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class UOnline_03_Cpp : ModuleRules
{
	public UOnline_03_Cpp(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		// 모듈 라이브러리들
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });

		PrivateDependencyModuleNames.AddRange(new string[] {  });

		// ModuleDirectiory 디렉터리는 Sources 폴더 밑 프로젝트 폴더
		// 이 폴더를 기준으로 헤더를 불러들일 수 있도록 세팅
		PublicIncludePaths.Add(ModuleDirectory);
	}
}

 

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

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