[UE5]툰 탱크-18

칼든개구리·2024년 12월 11일
0

[언리얼TO리얼]

목록 보기
26/42

A Projectile

발사체에는 스태틱 메시가 필요하다. 그래야 월드에서 스폰할 때 발사체를 볼 수 있기 때문이다.

발사체.h

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

#pragma once

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

UCLASS()
class TOONTANKS_API AProjectile : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AProjectile();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

private:
	UPROPERTY(EditDefaultsOnly, Category="Combat")
	UStaticMeshComponent* ProjectileMesh;
};

발사체.cpp

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

#include "Components/StaticMeshComponent.h"
#include "Projectile.h"

// Sets default values
AProjectile::AProjectile()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = false; //발사체에는 틱이 필요없으므로 false

	ProjectileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Projectile Mesh"));
	RootComponent = ProjectileMesh;
}

// Called when the game starts or when spawned
void AProjectile::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AProjectile::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

기본적인 ProejctileMesh하나를 만들고 블루프린트 클래스를 하나 만들어 주었다.


메시를 골라주면 발사체가 만들어졌다!

Spawning Actors

발사체 생성 액터는 SpawnActor 함수가 있어야 한다.
우리는 c++ 함수를 호출해 동적으로 새로운 개체를 생성할 것이다. 우리는 블루프린트보다 c++에서 만들기 원하는데, AProjectile이라는 c++에 기반한 블루프린트에 추가적인 정보가 있기 때문이다(정적 메시 컴포넌트로 선택한 메시). 메시를 얻기 위해서는 블루프린트 버전으로 생성해야 한다.
그러면 c++에서 블루프린트 기반 객체를 어떻게 생성한다는 것일까?

TSubclassOf

이것은 탬플릿이다. TSubclassOf는 타입을 파라미터로 가지고 UClass라는 걸 저장하는 변수를 갖게 해준다. UClass는 클래스 타입이지만 언리얼 엔진의 리플렉션 시스템과 상호작용할 수 있 습니다. 여기서 리플렉션 시스템이란 C++와 블루프린트 사이 정보를 교환하는 것을 말합니다.
TSubclassOf는 이름에서 알 수 있듯이 전달하는 타입이나 그 타입의 하위 클래스를 기반으로 클래스를 나타내는 변수를 만들 수 있습니다. 우리가 타입을 선택할 수 있고 TSubclassOf는 그에 따른 모든 타입을 나타내는 UClass를 보유할 수 있게 한다. 타입을 기반으로 한 블루프린트도 마찬가지다.

Spawning Actors

왜 굳이 TSubclassOf변수를 만들었을까?
Spawn Actor가 동작하는 방법에 대해서 먼저 알고 있어야 한다. SpawnActor은 UWorld 클래스에 속하는 함수다. world를 가져오면 SpawnActor을 호출할 수 있다. SpawnActor은 또 다른 템플릿 함수이고 기본 하위 객체를 생성하는 것과 유사하게 새로운 객체를 생성하도록 되어 있다.
기본 하위 객체를 생성하는 것은 컴포넌트를 생성하기 위해 설계되었고 우리는 특정 클래스를 위한
생성자에서만 사용할 수 있다. SpawnActor는 게임이 실행되는동안 호출될 수 있고 액터를 생성한다. 이는 템플릿이기 때문에 형식이 필요한데, 발사체를 생성하고 싶다면 c++ 클래스 타입에 AProjectile을 넘기면 된다 SPawnActor<"AProjectile">()
이것은 C++의 SpawnActor 함수가 반환하는 c++ 클래스인 것이다. 괄호 안에는 UClass를 포함한 매개변수가 들어간다(UClass, Location, Rotation). UClss*는 발사체를 생성하는 타입을 나타낸다. 이것이 생성되는 객체의 실제 타입이다. Location은 객체를 어디로 생성할지 결정하는 FVector이고 Rotation은 회전을 지정한다. 예를 들면 SpawnActor<"AProjectile">(ProjectileClass, Loc, Rot) 이렇다.

UClass

UClasss는 클래스 타입이다. SpawnActor을 호출할 때 UClass를 넘겨 SPawnActor 함수와 객체에 관한 정보를 제공한다. SpawnActor에게 어떤 c++ 타입을 만들어야 하는지 알려준다.
AProjectile을 기반으로 블루프린트를 생성하고 블루프린트에서 속성을 설정한다고 생각해보자.
만약 우리가 c++ 클래스 자체를 생성한다면 정적 메시는 새로 생긴 발사체 객체에 적용될 지 않을 것이다. 눈에 보이지 않은 액터가 생긴 것이다. 하지만 UClass 변수는 블루프린트 클래스를 나타낸다. UClass는 C++ 쪽에서 변수를 가지게 해준다(블루프린트 타입). SpawnActor은 그 클래스를 인풋 매개 변수로 받아 UClass로 정의되는 블루프린트에 기반하여 새로운 객체를 생성한다.
새로운 발사체는 정적 메시 속성 집합을 가진다. c++클래스가 아닌 블루프린트에 기반한 새로운 객체를 생성하기 때문이다. 이것이 TSubclassOf를 만든 이유다. UClass를 저장하고 BP_Tank 블루 프린트에서 BP_Projectile롸 동일하게 설정할 수 있기 때문이다.
이제 액터를 만들어 본다
GetWorld()-> SpawnActor()로 호출하면 이 함수에 인풋으로 C++타입을 꺾쇠 괄호 안에 넣어야 한다는 것을 알 수 있다.

	UPROPERTY(EditDefaultsOnly, Category = "Combat")
	TSubclassOf<class AProjectile> ProjectileClass; //클래스 타입을 나타내는 C++변수, 타입은 AProjectile
void ABasePawn::Fire()
{
	FVector Location = ProjectileSpawnPoint->GetComponentLocation(); 
	FRotator Rotation = ProjectileSpawnPoint->GetComponentRotation();
	

	GetWorld()->SpawnActor<AProjectile>(ProjectileClass, Location, Rotation );
}


베럴의 끝에서 발사체가 만들어지고 공중에 그냥 떠있는 것이 이상해 보이지만 아직 1단계다!!

TIL: 발사체 액터를 생성하는 것이 이렇게 어려운 일이구나...TSubclassOf 부터 이제 머리에 한계가 오기 시작했다. Spawn되는 액터를 Projectile로 만들어준다는건가?.. 다시 정리하면서 읽어봐야겠다.

오늘 한 것을 살짝 정리해본다
1. TSubclassOf란?

  • 정의: 특정 클래스 또는 그 하위 클래스를 참조할 수 있는 변수를 만드는 탬플릿이다.
  • 목적: 특정 클래스나 블루 프린트 기반 클래스의 정보를 저장하기 위해 사용하며 이 변수는 UClass를 통해 블루프린트와 C++을 상호작용 가능하게 한다.
TSubclassOf<AProjectile> ProjectileClass;
  • ProjectileClass 변수는 AProjectile 또는 AProjectile을 상속받은 블루프린트 기반 클래스 정보를 저장할 수 있습니다.
  1. 블루 프린트 이야기가 나오는 이유
  • 블루프린트 기반 클래스에는 C++코드에서 정의하지 않은 추가적인 속성(정적 메시)이 있을 수 있다
  • TSubclassOf를 사용하면 블루프린트로 확장된 클래스(BP_Projectile)를 C++에서 동적으로 생성할 수 있다.

상황 예시:

  • AProjectile이라는 C++ 클래스가 있습니다.
  • BP_Projectile은 AProjectile을 상속받은 블루프린트입니다.
  • BP_Projectile에서 발사체의 메시와 같은 속성을 설정했습니다.
  • C++에서 이 블루프린트 기반 객체를 생성하려면 UClass를 통해 블루프린트를 참조해야 합니다.
  1. SpawnActor와 TSubclassOf의 관계
  • SpawnActor 함수는 C++에서 액터를 동적으로 생성하는데 사용된다.
  • SpawnActor는 기본적으로 C++ 클래스 타입을 생성하지만, 블루프린트 기반 객체를 생성하려면 UClass 정보를 전달해야 한다.
  • TSubclassOf는 UClass 정보를 안전하게 저장하고 관리할 수 있다.
FVector Loc = FVector(0.0f, 0.0f, 0.0f);
FRotator Rot = FRotator::ZeroRotator;

// TSubclassOf 변수로 블루프린트 클래스 참조
if (ProjectileClass)
{
    GetWorld()->SpawnActor<AProjectile>(ProjectileClass, Loc, Rot);
}
  • ProjectileClass는 블루프린트 기반 객체(BP_Projectile) 정보를 가지고 있습니다.
  • 이를 통해 BP_Projectile에 설정된 메시와 속성까지 포함된 객체를 생성할 수 있습니다

결론

  • TSubclassOf의 역할: 특정 클래스나 블루프린트 기반 클래스를 참조하고, 이를 통해 C++에서 블루프린트를 기반으로 객체를 생성할 수 있게 합니다.
  • 블루프린트가 중요한 이유:
    -블루프린트는 속성을 설정하거나 C++ 클래스의 확장된 기능을 추가할 수 있습니다.
    -C++에서 이를 활용하려면 UClass와 TSubclassOf가 필요합니다.
  • SpawnActor 사용:
    -SpawnActor는 C++ 클래스 또는 블루프린트 기반 객체를 생성할 수 있습니다.
    -블루프린트 기반 객체를 생성하려면 TSubclassOf를 통해 UClass 정보를 제공해야 합니다.

예를 들어 정리
1. C++에서 AProjectile이라는 클래스가 있고, 이를 기반으로 블루프린트 BP_Projectile을 생성했습니다
2. BP_Projectile에서 메시와 속성을 설정했습니다.
3. 게임 도중 이 블루프린트를 기반으로 발사체를 생성하려면:

  • TSubclassOf<;AProjectile> 변수에 BP_Projectile의 정보를 참조합니다.
  • SpawnActor로 동적으로 객체를 생성합니다.
profile
메타쏭이

0개의 댓글