1. 컴포넌트 만들고 붙이기

다양한 컴포넌트를 만들어 커스텀 폰에 붙여봅니다.

Windows
MacOS
Linux

언리얼 엔진 4 가 처음이신 분들은, 프로그래밍 퀵스타트 튜토리얼 먼저 살펴보시는 것이 좋습니다. 이 튜토리얼은 프로젝트 생성 및 C++ 코드 추가는 물론, 언리얼 에디터 에서의 입력 환경설정이 익숙하신 분들을 대상으로 합니다. Pawn 클래스 생성이나 입력 환경설정이 익숙치 않으신 경우, 플레이어 입력 및 폰 튜토리얼 부터 시작해 보시면 좋습니다.

  1. 시작용 콘텐츠를 포함해서 기본 코드 프로젝트를 새로 만드는 것으로 시작합니다. 이름은 "HowTo_Components" 로 짓습니다. 먼저 이 프로젝트에 추가시켜 줄 것은, 우리 컴포넌트 를 담아 레벨을 돌아다니고 입체 오브젝트와 충돌하게 될 커스텀 입니다. 이 튜토리얼에서는 이름을 "CollidingPawn" 이라 짓겠습니다.

    ChooseParentClass.png

    NamePawnClass.png

  2. Visual Studio 에서 CollidingPawn.h 를 열고 클래스 정의 하단에 다음 코드를 추가해 줍니다:

    UParticleSystemComponent *OurParticleSystem;

    이 변수를 사용해서 나중에 만들 Particle System 컴포넌트의 기록을 유지하도록 하겠습니다. 기록할 변수를 만들지 않고 컴포넌트 를 만들 수는 있지만, 코드에서 그 컴포넌트 를 사용하려면, 이렇게 클래스 멤버 변수에 저장해야 합니다.

  3. 이제 CollidingPawn.cpp 를 열고 ACollidingPawn::ACollidingPawn 생성자 함수를 편집, 여러가지 유용한 컴포넌트 를 스폰시킬 코드를 추가하고, 계층구조로 배치합니다. 물리 월드와의 상호작용을 위한 Sphere 컴포넌트, 콜리전 모양을 시각적으로 나타내 줄 Static Mesh 컴포넌트, 마음대로 켜고 끌 수 있는 Particle System 컴포넌트, 게임내 시점 제어를 위해 Camera 컴포넌트에 붙일 Spring Arm 컴포넌트를 만들겠습니다.

  4. 먼저 계층구조의 루트가 될 컴포넌트 를 결정해야 합니다. 이 튜토리얼에서는 Sphere 컴포넌트로 갈텐데, 물리적 실존이 있고 게임 월드와의 상호작용 및 충돌이 가능하기 때문입니다. 참고로 액터 에는 계층구조 내 다수의 물리 기반 컴포넌트 가 있을 수 있지만, 이 튜토리얼에서는 하나면 됩니다.

        // 루트 컴포넌트는 물리에 반응하는 구체가 됩니다
        USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
        RootComponent = SphereComponent;
        SphereComponent->InitSphereRadius(40.0f);
        SphereComponent->SetCollisionProfileName(TEXT("Pawn"));
  5. 다음, 반경이 50 인 스태틱 메시 애셋에서 눈에 보이는 구체를 만들어 붙여줍니다. 방금 만든 반경 40 의 Sphere 컴포넌트와 완전히 맞아떨어지지 않으므로, 스케일을 80% 로 줄여줍니다. 중심도 맞춰주려면 40 유닛 아래로 내려주기도 해야 합니다.

        // 구체가 어딨는지 확인할 수 있도록 메시 컴포넌트 생성 및 위치 조정
        UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
        SphereVisual->SetupAttachment(RootComponent);
        static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
        if (SphereVisualAsset.Succeeded())
        {
            SphereVisual->SetStaticMesh(SphereVisualAsset.Object);
            SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));
            SphereVisual->SetWorldScale3D(FVector(0.8f));
        }

    코드로 스태틱 메시 애셋의 위치를 확인할 수는 있지만, 애셋 경로를 하드코딩하는 것은 별로 바람직한 애셋 로드 방식이 아닙니다. 클래스에서 컴포넌트 를 사용한다면 보통은 코드로 컴포넌트 자체를 만든 다음, 언리얼 에디터 에서 선택하는 것이 낫습니다. 물론 이 작업은 코드에서 바로 할 수도 있으며, 새로운 기능을 만들거나 디버깅을 하는 프로그래머에게는 더 빠를 수도 있습니다.

  6. 이제 계층구조에 비활성 Particle System 컴포넌트를 붙일 수 있습니다. 이 컴포넌트는 코드로 조작할 수 있으며, 나중에 켜고 끄는 입력 구성을 해 주겠습니다. 참고로 Particle System 컴포넌트는 루트가 아닌 Static Mesh 컴포넌트에 붙어있습니다. 또 플레이 도중 더욱 잘 보이라고 메시의 하단 중앙에서 약간 오프셋이 적용되어 있습니다.

        // 활성화 또는 비활성화시킬 수 있는 파티클 시스템 생성
        OurParticleSystem = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("MovementParticles"));
        OurParticleSystem->SetupAttachment(SphereVisual);
        OurParticleSystem->bAutoActivate = false;
        OurParticleSystem->SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f));
        static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire"));
        if (ParticleAsset.Succeeded())
        {
            OurParticleSystem->SetTemplate(ParticleAsset.Object);
        }
  7. Spring Arm 컴포넌트는 보다 느린 가속 / 감속을 따라다니는 카메라에 적용시킬 수 있어, 카메라의 부드러운 부착점이 됩니다. 카메라가 입체 오브젝트를 뚫고 지나가지 못하도록 하는 기능도 내장되어 있어, 삼인칭 게임에서 플레이어가 구석에서 벽을 등지는 상황에 유용합니다. 필수는 아니지만, 게임에 보다 부드러운 느낌의 카메라 작업을 아주 빠르고 쉽게 얻어낼 수 있습니다.

        // 스프링 암을 사용하여 카메라에 부드럽고 자연스러운 모션을 적용합니다.
        USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraAttachmentArm"));
        SpringArm->SetupAttachment(RootComponent);
        SpringArm->RelativeRotation = FRotator(-45.f, 0.f, 0.f);
        SpringArm->TargetArmLength = 400.0f;
        SpringArm->bEnableCameraLag = true;
        SpringArm->CameraLagSpeed = 3.0f;
  8. 실제 Camera 컴포넌트는 만들기도 쉽고, 별도의 세팅도 필요치 않습니다. Spring Arm 에는 소켓 이 내장되어 있어, 베이스가 아닌 이 곳에 붙일 수 있습니다.

        // 카메라를 만들어 스프링 암에 붙입니다.
        UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera"));
        Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
  9. 컴포넌트를 만들어 붙였으니, 이 을 기본 플레이어가 조종하도록 설정해 줘야 합니다. 다음과 같은 코드면 됩니다:

        // 기본 플레이어 컨트롤 획득
        AutoPossessPlayer = EAutoReceiveInput::Player0;

새로운 에 유용한 컴포넌트 를 붙이기만 했는데 벌써 사용자 제어 환경설정이 다 됐습니다. 이제 언리얼 에디터 로 돌아옵니다.

작업중 코드

CollidingPawn.h

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "GameFramework/Pawn.h"
#include "CollidingPawn.generated.h"

UCLASS()
class HOWTO_COMPONENTS_API ACollidingPawn : public APawn
{
    GENERATED_BODY()

public:
    // Sets default values for this pawn's properties
    ACollidingPawn();

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

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

    // Called to bind functionality to input
    virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;

    UParticleSystemComponent* OurParticleSystem;
};

CollidingPawn.cpp

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "HowTo_Components.h"
#include "CollidingPawn.h"

// Sets default values
ACollidingPawn::ACollidingPawn()
{
    // Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    // Our root component will be a sphere that reacts to physics
    USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
    RootComponent = SphereComponent;
    SphereComponent->InitSphereRadius(40.0f);
    SphereComponent->SetCollisionProfileName(TEXT("Pawn"));

    // Create and position a mesh component so we can see where our sphere is
    UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
    SphereVisual->SetupAttachment(RootComponent);
    static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
    if (SphereVisualAsset.Succeeded())
    {
        SphereVisual->SetStaticMesh(SphereVisualAsset.Object);
        SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));
        SphereVisual->SetWorldScale3D(FVector(0.8f));
    }

    // Create a particle system that we can activate or deactivate
    OurParticleSystem = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("MovementParticles"));
    OurParticleSystem->SetupAttachment(SphereVisual);
    OurParticleSystem->bAutoActivate = false;
    OurParticleSystem->SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f));
    static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire"));
    if (ParticleAsset.Succeeded())
    {
        OurParticleSystem->SetTemplate(ParticleAsset.Object);
    }

    // Use a spring arm to give the camera smooth, natural-feeling motion.
    USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraAttachmentArm"));
    SpringArm->SetupAttachment(RootComponent);
    SpringArm->RelativeRotation = FRotator(-45.f, 0.f, 0.f);
    SpringArm->TargetArmLength = 400.0f;
    SpringArm->bEnableCameraLag = true;
    SpringArm->CameraLagSpeed = 3.0f;

    // Create a camera and attach to our spring arm
    UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera"));
    Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);

    // Take control of the default player
    AutoPossessPlayer = EAutoReceiveInput::Player0;
}

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

}

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

}

// Called to bind functionality to input
void ACollidingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
    Super::SetupPlayerInputComponent(InputComponent);

}
Select Skin
Light
Dark

새로운 언리얼 엔진 4 문서 사이트에 오신 것을 환영합니다!

문서 사이트에 대한 의견을 모을 수 있는 피드백 시스템을 포함해서 여러가지 새로운 기능을 준비하고 있습니다. 아래 Documentation Feedback 포럼(영문) 또는 언리얼 엔진 네이버 공식 카페(한글) 중 편하신 곳에 의견이나 문제점을 알려 주세요.

새 시스템이 준비되면 알려 드리겠습니다.

네이버 카페
공식 포럼