액터 찾기

블루프린트 스크립팅/C++를 사용하여 씬에서 액터를 찾는 방법을 다룬 튜토리얼입니다.

Choose your operating system:

Windows

macOS

Linux

프로젝트의 스케일이 커지기 시작하면 씬에서 개별 액터(Actor) 를 찾기가 어려울 수 있습니다. 레벨(Level) 세트 조각과 지오메트리부터 NPC, 적, 상호작용 가능한 오브젝트, 픽업에 이르기까지 씬에 수백 개의 액터가 생기는 일도 흔합니다. 언리얼 에디터 에서 작업할 때는 아웃라이너(Outliner) 를 사용하면 씬에서 액터를 찾기가 수월해집니다.

이미지 대체 텍스트

위 이미지의 오른쪽에 있는 아웃라이너에는 레벨에 배치된 모든 액터가 나열됩니다. 아웃라이너에 하이라이트된 액터 중 하나를 클릭하면 레벨 뷰포트(Level Viewport) 에서도 그 액터가 강조됩니다. 액터(Actor) 또는 타입(Type) 헤더를 클릭하여 아웃라이너를 액터 이름별 또는 타입별로 정렬할 수 있습니다. 타입 박스의 아래 화살표를 클릭하면 두 번째 카테고리를 타입에서 다른 필터로 변경할 수 있습니다.

아웃라이너에서 액터를 선택한 채로 레벨 뷰포트 안을 탐색하다가 액터를 더블클릭하거나 F 를 누르면 카메라가 선택한 액터 위치로 이동하여 액터에 포커스 를 맞춥니다.

씬에 있는 액터를 찾는 법에 관한 자세한 정보는 아웃라이너 문서를 참고하세요.

구현 방법 선택

블루프린트

C++

프로젝트 설정

이 튜토리얼에서는 Get All Actors Of Class 노드를 사용하여 레벨(Level) 에서 액터를 찾는 방법을 다룹니다. 이 노드는 호출될 경우 지정된 클래스의 레벨에 있는 모든 액터를 얻어서 배열(Array) 에 배치합니다. 그러면 해당 배열에서 필터 기준에 따라 액터를 얻을 수 있습니다. 그런 다음 액터의 프로퍼티에 액세스하거나, 구현하려는 기능에 따라 해당 프로퍼티를 수정할 수 있습니다.

  1. 먼저 새 프로젝트(New) > 게임(Games) > 삼인칭(ThirdPerson) > 블루프린트(Blueprint) 프로젝트 를 차례대로 선택하고 시작용 콘텐츠 사용(With Starter Content) 을 활성화하여 FindingActors 라는 프로젝트를 생성합니다.

    클릭하면 최대 크기로 볼 수 있습니다.

  2. 편집(Edit) > 프로젝트 세팅(Project Settings) > 엔진(Engine) > 입력(Input) > 바인딩(Bindings) > 액션 매핑(Action Mappings) 으로 이동한 후 추가 (+ )를 클릭하여 FindActorPressed 라는 새 액션 매핑을 생성합니다. 그다음에 키 값1 로 설정합니다.

    클릭하면 최대 크기로 볼 수 있습니다.

이 튜토리얼은 게임플레이 스태틱 클래스 라이브러리(Gameplay Statics Class Library) (Get All Actors of Class 노드)를 사용하여 레벨 에서 액터 를 찾는 방법을 다룹니다. 이 함수(노드)는 호출될 경우 레벨에 있는 지정된 클래스 의 모든 액터를 얻어서 배열(Array) 에 배치합니다. 그러면 해당 배열에서 필터 기준에 따라 모든 액터 또는 액터 하나를 얻을 수 있습니다. 그런 다음 액터의 프로퍼티에 액세스하거나, 구현하려는 기능에 따라 해당 프로퍼티를 수정할 수 있습니다.

  1. 먼저 새 프로젝트...(New) > 게임(Games) > 삼인칭(ThirdPerson) 을 차례대로 선택하고 시작용 콘텐츠 사용(Starter Content) 을 활성화하여 FindingActors 라는 C++ 프로젝트를 생성합니다.

    클릭하면 최대 크기로 볼 수 있습니다.

  2. 편집(Edit) > 프로젝트 세팅(Project Settings) > 엔진(Engine) > 입력(Input) > 바인딩(Bindings) > 액션 매핑(Action Mappings) 으로 이동한 후 추가(+) 를 클릭하여 FindActorPressed 라는 새 액션 매핑을 생성합니다. 그다음에 키 값1 로 설정합니다.

    클릭하면 최대 크기로 볼 수 있습니다.

블루프린트 FireEffect 액터 생성하기

StarterContent 폴더에는 완성된 FireEffect 액터가 있으며, 이 액터에는 화염 이펙트를 연출할 수 있는 파티클 컴포넌트(Particle Component) 와 사운드 이펙트를 연출할 수 있는 오디오 컴포넌트(Audio Component) 가 포함되어 있습니다. 이 액터는 Get All Actors Of Class 노드에서 찾을 베이스 액터 클래스로 사용될 것입니다.

콘텐츠(Content) > StarterContent > Blueprints 로 이동하여 Blueprint_Effect_Fire 인스턴스를 월드로 드래그합니다.

03_BPDragBPEffectFire.png

  1. 추가(Add) 버튼을 클릭하여 새로운 C++ 클래스(New C++ Class) 를 생성한 다음, 부모 클래스 선택(Choose a Parent Class) 메뉴에서 액터(Actor) 를 선택하고 다음(Next) 을 클릭합니다.

    클릭하면 최대 크기로 볼 수 있습니다.

  2. 새 스타일 액터 클래스의 이름을 FireEffect 로 지정한 다음 클래스 생성(Create Class) 을 클릭합니다.

    클릭하면 최대 크기로 볼 수 있습니다.

  3. FireEffect.h 에서 아래의 코드를 선언합니다.

    public:
        //파이어 사운드 이펙트 오디오 컴포넌트를 가져옵니다.
        UAudioComponent* GetFireAudioComponent() const { return FireAudioComponent; }
    
        //파이어 이펙트 파티클 시스템 컴포넌트를 가져옵니다.
        UParticleSystemComponent* GetParticleFireComponent() const { return ParticleFireComponent; }
    
    protected:
        UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
        UParticleSystemComponent* ParticleFireComponent;
    
        UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
        UAudioComponent* FireAudioComponent;
  4. FireEffect.cpp 파일로 이동하여 아래의 클래스 라이브러리를 포함합니다.

    #include "Particles/ParticleSystemComponent.h"
    #include "Components/AudioComponent.h"
  5. AFireEffect 생성자에서 아래의 코드를 구현합니다.

    AFireEffect::AFireEffect()
    {
        // 이 액터가 프레임마다 Tick()을 호출하도록 설정합니다.  이 설정이 필요 없는 경우 비활성화하면 퍼포먼스가 향상됩니다.
        PrimaryActorTick.bCanEverTick = true;
        ParticleFireComponent = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("P_Fire"));
        FireAudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("Fire Audio"));
        ParticleFireComponent->SetupAttachment(RootComponent);
        FireAudioComponent->AttachToComponent(ParticleFireComponent,FAttachmentTransformRules::KeepRelativeTransform);
    }
  6. 코드를 컴파일(Compile) 합니다.

  7. 콘텐츠 브라우저(Content Browser) > C++ 클래스(C++ Classes) > FindingActors 로 이동한 후 FireEffect 액터를 우클릭하고 BP_FireEffect 라는 FireEffect 기반 블루프린트 클래스를 생성 합니다.

    05_CreateBPClassBased.png

  8. BP_FireEffect클래스 디폴트(Class Defaults) 에서 컴포넌트(Components) 패널에 있는 Particle Fire 를 클릭한 다음, 디테일(Details) 패널로 이동하여 Particle 카테고리에서 Template 드롭다운 메뉴를 열고 P_Fire 를 선택합니다.

    06_AddTemplateToBPFireEffect.png

  9. 컴포넌트(Components) 패널에서 Fire Audio 를 클릭한 다음, 디테일(Details) 패널로 이동합니다. Sound 카테고리에서 Sound 변수 드롭다운 메뉴를 열고 Fire01_Cue 를 선택합니다.

    07_AddSoundToBPFireEffect.png

  10. 컴파일(Compile)저장(Save) 을 클릭합니다.

    08_CompileSaveButton.png

완성된 코드

FireEffectActor.h

    #pragma once

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

    UCLASS()
    class FINDINGACTOR_API AFireEffect : public AActor
    {
        GENERATED_BODY()

    public: 
        // 이 액터 프로퍼티의 디폴트값 설정
        AFireEffect();

    protected:
        // 게임 시작 또는 스폰 시 호출
        virtual void BeginPlay() override;

    public: 
        // 프레임마다 호출
        virtual void Tick(float DeltaTime) override;

    public:
        //파이어 사운드 이펙트 오디오 컴포넌트를 가져옵니다.
        UAudioComponent* GetFireAudioComponent() const { return FireAudioComponent; }

        //파이어 이펙트 파티클 시스템 컴포넌트를 가져옵니다.
        UParticleSystemComponent* GetParticleFireComponent() const { return ParticleFireComponent; }

    protected:
        UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
        UParticleSystemComponent* ParticleFireComponent;

        UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
        UAudioComponent* FireAudioComponent;
    };

FireEffectActor.cpp

    #include "FireEffect.h"
    #include "Particles/ParticleSystemComponent.h"
    #include "Components/AudioComponent.h"

    // 디폴트값 설정
    AFireEffect::AFireEffect()
    {
        // 이 액터가 프레임마다 Tick()을 호출하도록 설정합니다.  이 설정이 필요 없는 경우 비활성화하면 퍼포먼스가 향상됩니다.
        PrimaryActorTick.bCanEverTick = true;
        // 이 액터가 프레임마다 Tick()을 호출하도록 설정합니다.  이 설정이 필요 없는 경우 비활성화하면 퍼포먼스가 향상됩니다.

        PrimaryActorTick.bCanEverTick = true;
        ParticleFireComponent = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("P_Fire"));
        FireAudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("Fire Audio"));
        ParticleFireComponent->SetupAttachment(RootComponent);
        FireAudioComponent->AttachToComponent(ParticleFireComponent, FAttachmentTransformRules::KeepRelativeTransform);
    }

    // 게임 시작 또는 스폰 시 호출
    void AFireEffect::BeginPlay()
    {
        Super::BeginPlay();
    }

    // 프레임마다 호출
    void AFireEffect::Tick(float DeltaTime)
    {
        Super::Tick(DeltaTime);
    }

삼인칭 캐릭터: Finding Actor Pressed 이벤트 세팅

  1. 콘텐츠(Content) > ThirdPerson > Blueprints 폴더로 이동하고 BP_ThirdPersonCharacter 를 더블클릭하여 클래스 디폴트(Class Defaults) 를 엽니다.

    04_OpenBPThirdPersonCharacter.png

  2. 이벤트 그래프(Event Graph) 를 우클릭한 다음, 액션(Actions) 메뉴에서 FindActorPressed 액션 키 이벤트를 검색합니다.

    Copy Node Graph

    05_BPScript01.png

  3. FindActorPressed 노드 키 이벤트에 있는 Pressed 핀에서 드래그하여 액션(Actions) 메뉴에서 Get All Actors Of Class 노드를 검색합니다.

    Copy Node Graph

    06_BPScript02.png

  4. Get All Actors Of Class 노드의 Actor Class 를 클릭하고 드롭다운에서 Blueprint_Effect_Fire 클래스를 선택합니다.

    07_BPScript03.png

  5. Out Actors 핀에서 드래그하여 액션(Actions) 메뉴에서 For Each Loop 를 검색합니다.

    Copy Node Graph

    08_BPScript04.png

  6. Get All Actors Of Class 노드의 실행 핀에서 드래그하여 For Each Loop 노드의 실행 핀에 연결합니다.

    Copy Node Graph

    09_BPScript05.png

  7. For Each Loop 노드의 Array Element 핀에서 드래그하여 액션(Actions) 메뉴에서 Get P Fire 를 검색합니다.

    Copy Node Graph

    10_BPScript06.png

  8. Array Element 핀을 밖으로 드래그한 다음, 액션(Actions) 메뉴에서 Get Fire Audio 를 검색합니다.

    Copy Node Graph

    11_BPScript07.png

  9. P Fire 핀에서 드래그하여 액션(Actions) 메뉴에서 비활성화(Deactivate) 노드를 찾습니다.

    Copy Node Graph

    12_BPScript08.png

  10. Fire Audio 핀에서 드래그하여 비활성화(Deactivate) 노드의 타깃(Target) 핀에 연결합니다.

    Copy Node Graph

    13_BPScript09.png

  11. 컴파일(Compile)저장(Save) 을 클릭합니다.

    14_CompileSaveButton.png

  1. 콘텐츠 브라우저(Content Browser) 에서 C++ 클래스(C++ Classes) > FindingActors 로 이동한 다음, FindingActorsCharacter 를 더블클릭하여 FindingActorsCharacter.h 파일을 엽니다.

    09_OpenFindingActors.png

  2. FindingActorsCharacter 클래스 디폴트에서 아래의 코드를 선언합니다.

    protected:
        void OnFindActorPressed();
  3. FindingActorsCharacter.cpp 로 이동하여 아래의 클래스 라이브러리를 포함합니다.

    #include "Kismet/GameplayStatics.h"
    #include "FireEffect.h"
    #include "Particles/ParticleSystemComponent.h"
    #include "Components/AudioComponent.h"

    언리얼 엔진은 Include-What-You-Use(IWYU ) 종속성 모델을 사용합니다. 즉, 엔진의 소스 코드가 컴파일에 필요한 종속성만 포함한다는 의미입니다. 추가 정보는 IWYU 문서를 참조하세요.

  4. 아래의 코드를 선언하여 OnFindActorPressed 에 적용될 로직을 구현합니다.

    void AFindingActorsCharacter::OnFindActorPressed()
    {
        TArray<AActor*> ActorsToFind;
        if(UWorld* World = GetWorld())
        {
        UGameplayStatics::GetAllActorsOfClass(GetWorld(), AFireEffect::StaticClass(), ActorsToFind);
        }
        for (AActor* FireEffectActor: ActorsToFind)
        {
            //이 액터의 유형이 FireEffect 클래스인지 여부입니다.
            AFireEffect* FireEffectCast = Cast<AFireEffect>(FireEffectActor);
            if (FireEffectCast)
            {
                //파이어 파티클 컴포넌트를 가져와 비활성화합니다.            
                FireEffectCast->GetParticleFireComponent()->Deactivate();
    
                //파이어 오디오 컴포넌트를 가져와 비활성화합니다.            
                FireEffectCast->GetFireAudioComponent()->Deactivate();
            }   
        }
    }
  5. SetupPlayerInputComponent 메서드로 이동하여 다음 코드를 선언합니다.

    void AFindingActorsCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
    {
        PlayerInputComponent->BindAction("FindActorPressed", IE_Pressed, this, &AFindingActorsCharacter::OnFindActorPressed);
    }
  6. 코드를 컴파일합니다.

완성된 블루프린트

Copy Node Graph

15_BPScriptFinal1.png

완성된 코드

FindingActorsCharacter.h

    #pragma once

    #include "CoreMinimal.h"
    #include "GameFramework/Character.h"
    #include "FindingActorsCharacter.generated.h"

    UCLASS(config=Game)

    class AFindingActorsCharacter : public ACharacter

    {
        GENERATED_BODY()

        /** 캐릭터 뒤에 카메라를 배치하는 카메라 붐 */
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
        class USpringArmComponent* CameraBoom;

        /** 카메라 따라가기 */
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
        class UCameraComponent* FollowCamera;

    public:

        AFindingActorsCharacter();

        /** 베이스 회전 속도, 단위는 도(º)/초. 다른 스케일 값 조절로 인해 최종 회전 속도가 영향을 받을 수 있습니다. */
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Input)
        float TurnRateGamepad;

    protected:

        /** 앞뒤 입력으로 호출 */
        void MoveForward(float Value);

        /** 좌우 입력으로 호출 */
        void MoveRight(float Value);

        /** 
         * 입력을 통해 호출되어 지정된 속도로 회전 
         * @param Rate  정규화된 비율이며, 1.0인 경우 지정된 회전 속도의 100%를 의미합니다.
         */
        void TurnAtRate(float Rate);

        /**
         * 입력을 통해 호출되어 지정된 속도로 올려다보기/내려다보기 
         * @param Rate  정규화된 비율이며, 1.0인 경우 지정된 회전 속도의 100%를 의미합니다.
         */
        void LookUpAtRate(float Rate);

        /** 터치 입력 시작 시 핸들러 */
        void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location);

        /** 터치 입력 중지 시 핸들러 */
        void TouchStopped(ETouchIndex::Type FingerIndex, FVector Location);

    protected:

        // APawn 인터페이스
        virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
        // APawn 인터페이스 종료

    public:

        /** CameraBoom 서브오브젝트 반환 **/
        FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }

        /** FollowCamera 서브오브젝트 반환 **/
        FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }

    protected:

        /** 플레이어 입력 컴포넌트에서 입력(Input) 키를 누르면 호출합니다. */
        void OnFindActorPressed();
    };

FindingActorsCharacter.cpp

    #include "FindingActorsCharacter.h"
    #include "Camera/CameraComponent.h"
    #include "Components/CapsuleComponent.h"
    #include "Components/InputComponent.h"
    #include "GameFramework/CharacterMovementComponent.h"
    #include "GameFramework/Controller.h"
    #include "GameFramework/SpringArmComponent.h"
    #include "Kismet/GameplayStatics.h"
    #include "FireEffect.h"
    #include "Particles/ParticleSystemComponent.h"
    #include "Components/AudioComponent.h"

    //////////////////////////////////////////////////////////////////////////
    // AFindingActorsCharacter

    AFindingActorsCharacter::AFindingActorsCharacter()
    {
        // 콜리전 캡슐 크기 설정
        GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);

        // 입력에 대한 회전 속도 설정
        TurnRateGamepad = 50.f;

        // 컨트롤러 회전 시 회전하지 않습니다. 카메라에만 영향을 미치도록 합니다.
        bUseControllerRotationPitch = false;
        bUseControllerRotationYaw = false;
        bUseControllerRotationRoll = false;

        // 캐릭터 무브먼트 환경설정
        GetCharacterMovement()->bOrientRotationToMovement = true; // 캐릭터가 입력 방향으로 이동    
        GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f); // 위의 캐릭터가 이동하는 회전 속도

        // 참고: 이 변수를 비롯한 많은 변수는 조정하기 위해 다시 컴파일하지 않고도
        // 캐릭터 블루프린트에서 미세조정하여 반복작업 시간을 단축할 수 있습니다.
        GetCharacterMovement()->JumpZVelocity = 700.f;
        GetCharacterMovement()->AirControl = 0.35f;
        GetCharacterMovement()->MaxWalkSpeed = 500.f;
        GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
        GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;

        // 카메라 붐 생성(콜리전 있을 시 플레이어 쪽으로 들어옴)
        CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
        CameraBoom->SetupAttachment(RootComponent);
        CameraBoom->TargetArmLength = 400.0f; // 캐릭터 뒤의 카메라가 이 거리에서 따라옴 
        CameraBoom->bUsePawnControlRotation = true; // 컨트롤러 기반으로 암 회전

        // 카메라 따라가기 생성
        FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
        FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // 카메라를 붐 끝에 어태치하여 붐이 컨트롤러 오리엔테이션에 맞추어 조절되도록 함
        FollowCamera->bUsePawnControlRotation = false; // 카메라가 암 기준으로 회전하지 않음

        // 참고: 캐릭터로부터 상속받는 메시 컴포넌트에 대한 스켈레탈 메시와 애님 블루프린트 레퍼런스는 
        // C++ 직접 콘텐츠 레퍼런스를 방지하기 위해 이름이 ThirdPersonCharacter인 파생 블루프린트 에셋에서 설정됨
    }

    //////////////////////////////////////////////////////////////////////////
    // 입력

    void AFindingActorsCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
    {
        // 게임플레이 키 바인딩 설정
        check(PlayerInputComponent);
        PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
        PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);

        PlayerInputComponent->BindAxis("Move Forward / Backward", this, &AFindingActorsCharacter::MoveForward);
        PlayerInputComponent->BindAxis("Move Right / Left", this, &AFindingActorsCharacter::MoveRight);

        // 2가지 버전의 회전 바인딩이 있어 서로 다른 종류의 디바이스를 다양한 방식으로 처리할 수 있습니다.
        // 'turn'은 마우스와 같은 절대 델타를 제공하는 디바이스를 처리합니다.
        // 'turnrate'는 아날로그 조이스틱과 같이 변화의 속도를 취급할 디바이스에 사용합니다.
        PlayerInputComponent->BindAxis("Turn Right / Left Mouse", this, &APawn::AddControllerYawInput);
        PlayerInputComponent->BindAxis("Turn Right / Left Gamepad", this, &AFindingActorsCharacter::TurnAtRate);
        PlayerInputComponent->BindAxis("Look Up / Down Mouse", this, &APawn::AddControllerPitchInput);
        PlayerInputComponent->BindAxis("Look Up / Down Gamepad", this, &AFindingActorsCharacter::LookUpAtRate);

        // 터치 디바이스 처리
        PlayerInputComponent->BindTouch(IE_Pressed, this, &AFindingActorsCharacter::TouchStarted);
        PlayerInputComponent->BindTouch(IE_Released, this, &AFindingActorsCharacter::TouchStopped);

        PlayerInputComponent->BindAction("FindActorPressed", IE_Pressed, this, &AFindingActorsCharacter::OnFindActorPressed);
    }

    void AFindingActorsCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location)
    {
        Jump();
    }

    void AFindingActorsCharacter::TouchStopped(ETouchIndex::Type FingerIndex, FVector Location)
    {
        StopJumping();
    }

    void AFindingActorsCharacter::TurnAtRate(float Rate)
    {
        // 속도 정보로부터 이 프레임에 대한 델타 계산
        AddControllerYawInput(Rate * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
    }

    void AFindingActorsCharacter::LookUpAtRate(float Rate)
    {
        // 속도 정보로부터 이 프레임에 대한 델타 계산
        AddControllerPitchInput(Rate * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
    }

    void AFindingActorsCharacter::MoveForward(float Value)
    {
        if ((Controller != nullptr) && (Value != 0.0f))
        {
            // 앞쪽 찾기
            const FRotator Rotation = Controller->GetControlRotation();
            const FRotator YawRotation(0, Rotation.Yaw, 0);

            // 앞쪽 벡터 구하기
            const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
            AddMovementInput(Direction, Value);
        }
    }

    void AFindingActorsCharacter::MoveRight(float Value)
    {
        if ( (Controller != nullptr) && (Value != 0.0f) )
        {
            // 오른쪽 찾기
            const FRotator Rotation = Controller->GetControlRotation();
            const FRotator YawRotation(0, Rotation.Yaw, 0);

            // 오른쪽 벡터 구하기 
            const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
            // 해당 방향으로 이동 추가
            AddMovementInput(Direction, Value);
        }
    }

    void AFindingActorsCharacter::OnFindActorPressed()
    {
        TArray<AActor*> ActorsToFind;
        if (UWorld* World = GetWorld())
        {
            UGameplayStatics::GetAllActorsOfClass(GetWorld(), AFireEffect::StaticClass(), ActorsToFind);
        }
        for (AActor* FireEffectActor : ActorsToFind)
        {
            //이 액터의 유형이 FireEffect 클래스인지 여부입니다.
            AFireEffect* FireEffectCast = Cast<AFireEffect>(FireEffectActor);
            if (FireEffectCast)
            {
                //파이어 파티클 컴포넌트를 가져와 비활성화합니다.            
                FireEffectCast->GetParticleFireComponent()->Deactivate();

                //파이어 오디오 컴포넌트를 가져와 비활성화합니다.           
                FireEffectCast->GetFireAudioComponent()->Deactivate();
            }
        }
    }

최종 결과물

툴바 로 이동하여 플레이(PIE) 를 클릭합니다.

16_PlayButton.png

숫자키 1 을 누르면 화염 이펙트 파티클이 사라지고 오디오 컴포넌트에서 발생하던 사운드 이펙트가 더 이상 들리지 않게 됩니다.

  1. 콘텐츠 브라우저(Content Browser) 로 이동하여 BP_FireEffect 인스턴스를 레벨(Level) 로 몇 개 드래그합니다.

    클릭하면 최대 크기로 볼 수 있습니다.

  2. 툴바 로 이동하여 플레이(PIE) 를 클릭합니다.

    11_PlayButton.png

  3. 숫자키 1 을 누르면 화염 이펙트 파티클이 사라지고 오디오 컴포넌트에서 발생하던 사운드 이펙트가 더 이상 들리지 않게 됩니다.

태그로 특정 액터 구하기

지금까지 Get All Actors Of Class 노드를 사용하여 지정된 클래스의 액터 배열을 가져오는 방법을 살펴봤습니다. 그러나 다양한 기준에 따라 배열 결과를 필터링하여 배열에서 특정 액터를 가져오는 방법도 있습니다. 이 방법에는 액터의 태그(Tags) 가 사용됩니다.

  1. 콘텐츠(Content) > StarterContent > Blueprints 로 이동하여 Blueprint_Effect_Fire 를 선택합니다.

    18_SelectBPEffectFire.png

  2. 디테일(Details) 패널에서 태그(Tags) 섹션으로 이동한 다음, 추가(+) 를 클릭하여 액터에 태그를 추가합니다.

    19_BPEffectFireDetails.png

  3. 0 엘리먼트 필드의 텍스트 스트링에 'FindActorTag' 를 입력합니다.

    20_BPEffectFireTag.png

  4. MyCharacter 블루프린트에서 For Each LoopArray Element 핀을 밖으로 드래그한 다음, 액션(Actions) 메뉴에서 Get Tags 를 찾습니다.

    Copy Node Graph

    21_BPScript10.png

  5. 태그(Tags) 핀에서 드래그하여 액션(Actions) 메뉴에서 Get (사본)(Get (a copy)) 노드를 찾습니다.

    Copy Node Graph

    22_BPScript11.png

    위의 이미지는 FindActorTag 로 설정한 인덱스 0에서 'Get'으로 태그를 구한 결과입니다.

  6. 블루프린트 스크립트는 다음과 같은 모습일 것입니다.

    Copy Node Graph

    23_BPScript12.png

  7. For Each Loop 노드의 실행 핀에서 드래그하여 액션(Actions) 메뉴에서 Branch 노드를 찾습니다.

    Copy Node Graph

    24_BPScript13.png

  8. Branch 노드의 Condition 핀에서 드래그하여 Actor Has Tag 노드를 추가합니다.

    Copy Node Graph

    25_BPScript14.png

  9. Get 노드의 Out 핀을 Actor Has Tag 노드의 Tag 핀에 연결합니다.

    26_BPScript15.png

  10. For Each Loop 노드의 Array Element 핀을 Actor Has Tag 노드의 Target 핀에 연결합니다. 블루프린트 스크립트는 다음과 같은 모습일 것입니다.

    27_BPScript16.png

  11. Branch 노드의 True 핀을 비활성화(Deactivate) 노드의 실행 핀에 연결합니다.

    28_BPScript17.png

  12. 블루프린트 스크립트는 다음과 같은 모습일 것입니다.

    Copy Node Graph

    29_BPScriptFinal2.png

  13. 컴파일(Compile)저장(Save) 을 클릭합니다.

    30_CompileSaveButton.png

  14. 아웃라이너(Outliner) 에서 하나의 Blueprint_FireEffect 를 선택한 후 디테일(Details) 패널에서 태그(Tags) 변수로 이동하여 FindActorTag 필드를 찾은 다음, 드롭다운 메뉴 를 열고 삭제(Delete) 를 선택하여 태그 변수를 삭제합니다.

    31_BPEffectFireDelTag.png

    기능을 보여 드리기 위해 태그가 없는 화염 이펙트 하나를 의도적으로 남겨두었습니다.

  15. 툴바 로 이동하여 플레이(PIE) 를 누릅니다.

    32_PlayButton.png

지금까지 게임플레이 스태틱 라이브러리의 GetAllActorsofClass 함수를 사용하여 지정된 클래스의 액터 배열을 가져오는 방법을 살펴봤습니다. 그러나 다양한 기준에 따라 배열 결과를 필터링하여 배열에서 특정 액터를 가져오는 방법도 있습니다. 이 방법에는 액터의 태그(Tags) 가 사용됩니다.

  1. 먼저 콘텐츠 브라우저(Content Browser) > C++ 클래스(C++ Classes) 폴더로 이동한 다음, FireEffect 액터 를 더블클릭하여 FireEffect.cpp 파일을 엽니다.

    12_OpenFireEffect.png

  2. FireEffect 생성자 내에 아래의 코드를 추가합니다.

    AFireEffect::AFireEffect()
    {
        Tags.Add(FName("FindActorTag"));
    }

    태그는 액터의 클래스 디폴트에 속하는 배열이며, 그룹화와 카테고리 분류에 사용할 수 있습니다.

  3. 코드를 컴파일(Compile) 합니다.

  4. BP_FireEffect 를 연 다음, 디테일(Details) 패널에서 액터(Actor) 카테고리로 이동하면 액터 태그가 생성된 것을 확인할 수 있습니다.

    13_AddedActorTag.png

  5. 콘텐츠 브라우저(Content Browser) > C++ 클래스(C++ Classes) 폴더 로 이동한 다음, FindingActorsCharacter 를 더블클릭하여 FindingActorsCharacter.cpp 파일을 엽니다.

    14_OpenFindingActors.png

  6. OnFindActorPressed 메서드에서 아래의 코드를 구현합니다.

    void AFindingActorsCharacter::OnFindActorPressed()
    {
    
        TArray<AActor*> ActorsToFind;
    
        //'FindActorTag'가 있는 FireEffect 클래스의 모든 액터를 가져옵니다.
        UGameplayStatics::GetAllActorsOfClassWithTag(GetWorld(), AFireEffect::StaticClass(), FName("FindActorTag"),ActorsToFind);
    
        for (AActor* FireEffectActor: ActorsToFind)
        {
            AFireEffect* FireEffectCast = Cast<AFireEffect>(FireEffectActor);
    
            if (FireEffectCast)
            {
                //파이어 파티클 컴포넌트를 가져와 비활성화합니다.
                FireEffectCast->GetParticleFireComponent()->Deactivate();
    
                //파이어 오디오 컴포넌트를 가져와 비활성화합니다. 
                FireEffectCast->GetFireAudioComponent()->Deactivate();
            }   
        }
    }
  7. 코드를 컴파일(Compile) 합니다.

  8. 레벨 뷰포트(Level Viewport) 에서 하나의 BP_FireEffect 인스턴스를 선택한 후 디테일(Details) 패널에서 태그(Tags) 변수로 이동하여 FindActorTag 필드를 찾은 다음, 그 옆에 있는 드롭다운 메뉴를 열고 태그 변수를 삭제합니다.

    15_BPEffectFireDelTag.png

  9. 툴바 로 이동하여 플레이(PIE) 를 클릭합니다.

    16_PlayButton2.png

최종 결과물

숫자키 1 을 누르면 ActorsToFindTag가 있는 Bluprint_Fire_ Effect 파티클은 모두 사라지지만, 해당 태그가 없는 불 이펙트는 그대로 유지됩니다.

숫자키 1 을 누르면 FindActorsTag가 있는 BP_FireEffect 파티클은 모두 사라지지만, 해당 태그가 없는 화염 이펙트는 그대로 유지됩니다.