Unreal Engine 4를 C++ 코드로 입력하기 앞서, 기본적인 개념과 변수타입을 지정하는 방법에 대해서 알아보자.
C++ 클래스에서 변수를 만들고 사용하기 위해서,
변수를 만들 헤더파일에서 변수의 타입과 그 변수를 인식하기 위한 이름을 적어줘야하고, 그 앞에 UPROPERTY 매크로를 붙여주면 된다.
UPROPERTY() Int 32 IntVariable;
이 UPROPERTY 매크로는 프로퍼티가 언리얼 엔진 및 에디터이러한 프로퍼티가 있음을 알리고, 연결되었을때 어떻게 작동할지를 지정하기 위한 것 이다.
정수는 0,1,2 같은 일반 숫자를 표현하는데 쓰이는 타입
기존의 C++ 에서는 short, int, long 을 쓰지만 플랫폼마다 길이가 달라질 수 있기 때문에, UE4 에서는 "int8", "int16","int32", "int64" 를 제공한다. int뒤에 붙어있는 8,16,32,64 는 정수를 표현하는데 몇개의 bit를 사용할 것인지를 의미한다.
int8 - 정수를 표현하는데 8개의 bit를 사용해서 127 ~ -128 까지의 숫자를 표현할 수 있고 int16 - 32,767 ~ -32,767 까지 표현할 수 있다. int32 - 214,648,647 부터 -214,648,647 까지 표현하고, int64 - 무려 9,223,372,036,854,775,807 부터 -9,223,372,036,854,775,807 까지 표현할 수 있다.
그렇다면, 왜 int64로 통일하여 프로그래밍을 하지 않는걸까?
그 이유는 모든 변수를 int64로 통일한다면, 최적화에 민감한 UE4에서의 성능 저하를 우려할수 있기때문이다.
그렇다면 각각의 변수의 타입을 맞춰 사용해야 하는데 그에 따른 부작용은 없을까!?
"Overflow" 와 "Underflow"
최적화에 성공하려면, 각각의 변수에 할당될 비트수를 예상 가능 범위만큼을 사용해야한다.
예를들어, int8을 사용할 것이라고 생각하고 int8을 사용했는데, 그 예상을 벗어나 127 + 1 = -128 이 되어버리거나 -128 에서 -1 을 했는데 127이 되어버리는 문제가 생긴다.
그렇기에, 그 범위를 넘어갈 가능성을 배제할 수 없다면, 예외처리를 통해 예방하는 방법을 사용해야한다.
c++ 과 같이 float은 float 과 double 을 가지며, float은 32 bit와 소수점 5자리까지의 정밀도를, double은 64bit와 그 두배인 10자리 숫자까지 정밀도를 가진다.
보통 C++ 에서는 "std::string" 을 사용하지만, 언리얼 C++ 에서는 필요에 따라 여러가지 클래스로 문자열을 제공한다.
가장 기본적으로 FString 을 사용한다. 저장되는 글자의 숫자에 따라, 변수의 길이가 자동으로 달라지는 타입으로 기본 C++의 std::string 과 유사하게 작동한다. FString 에서는 TEXT() 매크로를 사용해야한다.
현지화 텍스트를 위해서 FText 나 자주 사용되는 문자열을 식별자로 지정하여 문자열 비교할때 소모되는 메모리와 CPU 시간을 절약할수 있는 FName 그리고, 플랫폼 마다 다를 수 있는 문자열 세트와 상관없이 문자열을 저장하는 용도로 사용되는 TChart가 있다.
true와 false 값만 가지는 Boolean
기존 C++ 에서의 처럼 UE4 에도 Public, Private, Protected 이 있다.
public
public 멤버는 클래스의 내 외부 아무 곳에서나 접근할 수 있습니다.
protected
private와 비슷하지만 해당 클래스의 상속 클래스에서 접근할 수 있습니다.
private
private 멤버는 클래스 외부에서 접근할 수 없고 오직 클래스 내부에서만 접근이 가능합니다
MyActor.h
public: AMyActor(); UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Damage") int32 TotalDamege; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Damage") float DamageTimeInSeconds; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Transient, Category = "Damage") float DamagePerSecond; UPROPERTY() FString CharactorName; UPROPERTY() bool bAttackable; protected: virtual void BeginPlay() override; public: virtual void Tick(float DeltaTime) override;
MyActor.cpp (Default 값 설정)
AMyActor::AMyActor() { PrimaryActorTick.bCanEverTick = true; TotalDamage = 200; DamageTimeInSeconds = 1.0f; CharactorName = TEXT("JH"); bAttackable = true; }
우선, UPROPERTY 를 사용하여, 언리얼 엔진 및 에디터에 이러한 프로퍼티가 있음을 알리고, 연결 되었을 때, 어떻게 작동할지를 지정하기 위한것이다.
UPROPERTY Parameters
EditAnywhere : archytype(아직 인스턴스화 되지 않은 블루프린트의 원본을 의미)과 레벨에 배치된 인스턴스 양 쪽 모두의 property 창에서 편집 할 수 있음을 의미.
BlueprintReadWrite : 프로퍼티를 블루프린트에서 읽기와 쓰기가 모두 가능함을 의미.
BlueprintReadOnly: 프로퍼티를 블루프린트에서 읽기만 가능하게 해준다.
VisibleAnywhere: 프로퍼티를 모든 프로퍼티 창에서 보이지만, 편집할 수 없게 만든다.
Transient: 해당 프로퍼티가 휘발성 프로퍼티로 저장되지 않음을 의미한다.
Category: 블루프린트 편집 툴이나 디테일 패널에서 이 프로퍼티를 Damage 라는 카테고리로 묶어서 보여준다. 밀접한 관계를 가진 프로퍼티들을 같은 카테고리로 묶어두게 되면 에디터에서 작업할 때 필요한 프로퍼티를 빠르게 찾을 수 있다.
너무나 기본적인것들만 나열했는데, 웹개발보다 방대한 양의 자료를 공부하려니 머리가 지끈지끈 하다. 내가 만족하는 수준까지 올라가는데 얼마나 많은 포스팅을 해야할까 걱정되기도 하고.
앞으로, 최소, 한 주에 하나의 주제를 가지고 포스팅해보려한다. 화이팅..!