Unreal C++/C++ Actor Example2018. 11. 22. 00:45

C++ 액터 클래스를 이용하여 복잡한 로직을 작성하고 BP를 파생하여 사용하는 예


레벨 위에 TargetPoint 4개를 큰 사각형이 되도록 배치하고 그 위치를 향하여 계속 이동하는 큐브를 구현하고자 한다. 이러한 로직이 그다지 복잡한 것은 아니지만 블루프린트를 이용하기에는 적합하지 않을 정도로 복잡해지므로 C++ 액터 클래스를 생성하고 그 안에 사각형 운동을 하는 로직을 작성한 다음 완성된 C++액터 클래스를 기반으로 블루프린트 액터를 생성하여 사용하면 C++의 장점과 블루프린트의 장점을 동시에 활용할 수 있다


CppActor.h

#pragma once


#include "Runtime/Engine/Classes/Engine/TargetPoint.h"

#include "CoreMinimal.h"

#include "GameFramework/Actor.h"

#include "CppActor.generated.h"


UCLASS(Blueprintable, BlueprintType)

class CPP_TEST_API ACppActor : public AActor

{

GENERATED_BODY()

public:

// Sets default values for this actor's properties

ACppActor();


protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;


public:

// Called every frame

virtual void Tick(float DeltaTime) override;


UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cpp")

TArray<ATargetPoint *> Arr;


UFUNCTION(BlueprintCallable, Category = "Cpp")

void MoveRect(float DeltaTime);

};




위의 헤더파일에 Arr 배열의 원소가 포인터로 선언된 것은 블루프린트에서 취급되는 모든 UObject와 그 하위 클래스의 변수들은 모두 포인터이다. 언리얼 에디터에서 레퍼런스라고 부르고 있지만 C++의 레퍼런스와는 달리 언리얼의 레퍼런스는 포인터를 의미하는 경우가 많다

https://answers.unrealengine.com/questions/351656/pointer-to-uobject-and-inheritance-in-bpc.html

All UObject (and its descendants) variables are pointers.

Calling it a reference is misleading. It is not a reference (&), it is a pointer.



CppActor.cpp

#include "CppActor.h"

#include "../Public/CppActor.h"



// Sets default values

ACppActor::ACppActor()

{

  // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;


}


// Called when the game starts or when spawned

void ACppActor::BeginPlay()

{

Super::BeginPlay();

}


// Called every frame

void ACppActor::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);


}


void ACppActor::MoveRect(float DeltaTime)

{

static int idx = 0;

static FVector * SpdVec = new FVector(0.0F, 200.0F*DeltaTime, 0.0F);

FVector ALoc, NextLoc;

ALoc = GetActorLocation();

int next = idx + 1 == 4 ? 0 : idx + 1;

NextLoc = Arr[next]->GetActorLocation();


switch (idx) {

case 0:

if (ALoc.Y >= NextLoc.Y) {

ALoc.Y = NextLoc.Y;

idx++;

SpdVec->X = -200.0F * DeltaTime; SpdVec->Y = 0.0F; SpdVec->Z = 0.0F;

}

break;

case 1:

if (ALoc.X <= NextLoc.X) {

ALoc.X = NextLoc.X;

idx++;

SpdVec->X = 0.0F; SpdVec->Y =-200.0F * DeltaTime; SpdVec->Z = 0.0F;

}

break;

case 2:

if (ALoc.Y <= NextLoc.Y) {

ALoc.Y = NextLoc.Y;

idx++;

SpdVec->X = 200.0F * DeltaTime; SpdVec->Y =0.0F; SpdVec->Z = 0.0F;

}

break;

case 3:

if (ALoc.X >= NextLoc.X) {

ALoc.X = NextLoc.X;

idx=0;

SpdVec->X = 0.0F;  SpdVec->Y = 200.0F*DeltaTime; SpdVec->Z = 0.0F;

}

break;

}

ALoc += (*SpdVec);

SetActorLocation(ALoc);

}



위에 있는 헤더파일에는 아래와 같은 내용이 있다


UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cpp")

TArray<ATargetPoint *> Arr;


ATargetPoint 클래스 객체의 포인터를 원소로 하는 배열이 선언되어 있는데, 이 배열의 원소는 Blueprint에서 초기화하여 Arr 변수에 전달하기 위해 EditAnywhere 를 선언한 것이다. 위의 클래스를 드래그하여 레벨에 배치하거나 위의 클래스를 기반으로 블루프린트 클래스를 생성하여 블루프린트 에디터를 열고 [클래스 디폴트] 를 선택하고 우측 [디테일] 뷰를 보면 Arr변수의 원소를 초기화할 수 있는 항목이 나타난다


블루프린트에서 TargetPoint 배열을 선언할 때 원소의 자료형은 [TargetPoint 오브젝트 레퍼런스]형으로 지정해야 하고 [인스턴스 편집가능]을 선택하면 언리얼 에디터의 레벨 위에서 위의 액터를 선택했을 때 우측 Detail 뷰에서 배열의 원소를 할당할 수가 있으므로 레벨에 배치한 ATargetPoint을 선택하여 할당해 줄 수 있다


TargetPoint 레퍼런스 배열의 선언




위의 블루프린트에서 선언한 TargetPoint 참조배열에 원소를 초기화하는 예



블루프린트에서 생성하고 원소가 초기화된 배열을 C++의 TArray<AtargetPoint *> Arr 배열에 전달하는 블루프린트의 예

Posted by cwisky