본문 바로가기
Study/Unreal

[Unreal/정리] 캐릭터 선택

by generous_jeans 2020. 11. 9.

[ 캐릭터 선택 레벨 ] 

- 새 레벨 생성 - 

(언리얼 에디터) 파일-새 레벨 -> Defalut -> 현재 레벨 저장 -> Levels 이름 : "Select"

 

- Start에서 Select로 넘어가도록 설정 - 

(C++-StartLevelWidget.cpp)

void UStartLevelWidget::StartButtonCallback()
{
    UGameplayStatics::OpenLevel(GetWorld(), TEXT("Select"));
}

- 컨트롤러  생성 - 

(언리얼 에디터) Player -> 우클릭_블루프린트 클래스-부모 : "SelectPlayerController" 이름 : "BPSelectPlayController"

 

- 게임모드 생성 - 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++생성 -> 부모 : "BaseGameMode" 이름 : "SelectGameMode"

 

(언리얼 에디터)  월드 세팅 -> GameMode-게임모드 오버라이드 : "SelectGameMode"

 

- 위젯 생성 - 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++생성 -> 부모 : "UserWidget" 이름 : "SelectLevelWidget"

 

(언리얼 에디터) 위젯 블루프린트 -> 이름 : "UI_SelectLevel"

 

(언리얼 에디터-UI_SelectLevel) Button -> "StartButton" -> 변수인지 : "해제" 앵커 : "전체" 위치 조절 Apperence-이미지 설정(0.9 1.0 0.7 0.3) DrawAs : "Image"

(언리얼 에디터-UI_SelectLevel) Button -> "EndButton" -> 변수인지 : "해제" 앵커 : "전체" 위치 조절 Apperence-이미지 설정(0.9 1.0 0.7) DrawAs : "Image"

 

(언리얼 에디터-UI_SelectLevel) 그래프 -> 디테일 -> 부모클래스 : "SelectLevelWidget"

 

- 캐릭터 배치 - 

// 선택할 캐릭터 설정.

(언리얼 에디터) Player-> 우클릭_블루프린트 클래스 -> 부모 : "SelectPlayer" 이름 : "BPSelectWukong"

(언리얼 에디터) Player-> 우클릭_블루프린트 클래스 -> 부모 : "SelectPlayer" 이름 : "BPSelectCountess"

 

(언리얼 에디터-BPSelectWukong) 캡슐 컴포넌트 위치 조정. 회전 z : "-90"

(언리얼 에디터-BPSelectCountess) 캡슐 컴포넌트 위치 조정. 회전 z : "-90"

// Select용과 Play용을 따라 만드는 것이 좋음. 

 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++생성 -> 부모 : "AnimInstance" 이름 : "SelectAnimInstance"

 

(언리얼 에디터) Player-> 우클릭_애니메이션 블루프린트 클래스 -> 부모 : "SelectAnimInstance" "WukongSkeleton" 이름 : "BPSelectWukongAnim"

(언리얼 에디터) Player -> 우클릭_애니메이션 블루프린트 클래스 -> 부모 : "SelectAnimInstance" "CountessSkeleton" 이름 : "BPSelectCountessAnim"

 

(언리얼 에디터-BPSelectWukong) 디테일 -> Animation-Anim Class : "BPSelectWukongAnim"

(언리얼 에디터-BPSelectCountess) 디테일 -> Animation-Anim Class : "BPSelectCountessAnim"

 

(언리얼 에디터-BPSelectWukongAnim) 애니메이션 설정

스테이트 머신 : "Select"

Select->최종 애니메이션 포즈 연결

 

Select

Entry->Idle -> 디테일-Events-Always Reset on Entry : "체크"

Idle->Select -> 디테일-Events-Always Reset on Entry : "체크"

Select->Idle 연결

 

Idle->Select 트랜지션 룰

Get Anim Type -> ==(Select)

 

Select->Idle 트랜지션 룰

디테일 -> Automatic Rule Based .. : "체크" 

 

Idle

Idle 애셋->출력 애니메이션 포즈 -> 디테일-Loop Animtaion : "체크"

 

Select

Select 애셋->출력 애니메이션 포즈 -> 디테일-Loop Animtaion : "해제"

 

(언리얼 에디터-BPSelectCountessAnim) 애니메이션 설정

스테이트 머신 : "Select"

Select->최종 애니메이션 포즈 연결

 

Select

Entry->Idle -> 디테일-Events-Always Reset on Entry : "체크"

Idle->Select -> 디테일-Events-Always Reset on Entry : "체크"

Select->Idle 연결

 

Idle->Select 트랜지션 룰

Get Anim Type -> ==(Select)

 

Select->Idle 트랜지션 룰

디테일 -> Automatic Rule Based .. : "체크" 

 

Idle

Idle 애셋->출력 애니메이션 포즈 -> 디테일-Loop Animtaion : "체크"

 

Select

Select 애셋->출력 애니메이션 포즈 -> 디테일-Loop Animtaion : "해제"

 

(언리얼 에디터) 캐릭터 배치

 

- 캐릭터를 선택하면 모션을 실행하도록 설정 - 

SelectPlayerController에서 작업. 

 

(언리얼 에디터) 프로젝트 세팅 -> 엔진-입력 -> 액션 매핑- 마우스 "LButton" "RButton"

 

- 피킹 -

(언리얼 에디터-BPSelectWukong) 디테일 -> 콜리전-Can Character Step Up On : "No"

(언리얼 에디터-BPSelectWukong) 디테일 -> 콜리전-Collision Presets : "BlockAll"

(언리얼 에디터-BPSelectCountess) 디테일 -> 콜리전-Can Character Step Up On : "No"

(언리얼 에디터-BPSelectCountess) 디테일 -> 콜리전-Collision Presets : "BlockAll"

 

(언리얼 에디터-BPSelectWukongAnim) Notify "SelectEnd" 설정

(언리얼 에디터-BPSelectCountessAnim) Notify "SelectEnd" 설정

 

- 마우스 설정

(언리얼 에디터) 프로젝트 세팅 -> 엔진-유저 인터페이스 -> 소프트웨어 커러 : Default UIMouse

 

- 캐릭터 선택시 캐릭터 정보가 출력될 위젯 생성 -

(언리얼 에디터) C++클래스 -> 우클릭_새 C++생성 -> 부모 : "UserWidget" 이름 : "CharacterStateWidget"

 

(언리얼 에디터) UI -> 우클릭_위젯 블루프린트 -> 부모 : "UserWidget" 이름 : "UI_CharacterState"

 

(언리얼 에디터-UI_CharacterState) 부모클래스 : "CharacterStateWidget

 

(언리얼 에디터-UI_CharacterState) Canvas : 너비 : "300" 하이트 : "500"

(언리얼 에디터-UI_CharacterState) Image : "Back" 앵커 : "전체" 

(언리얼 에디터-UI_CharacterState) Image : "Character" 변수인지 : "체크" 

(언리얼 에디터-UI_CharacterState) Text : "NextText" 변수인지 : "해제" 

 

- 플레이어의 모습을 캡쳐해서 볼 수 있게 설정 - 

(언리얼 에디터) UI -> 우클릭_머터리얼&텍스처-렌더타깃 : "CharacterTexture"

 

(언리얼 에디터-CharacterTexture) 디테일-Clear Color : 0.0

(언리얼 에디터-CharacterTexture) 디테일-Size X : 1920 Size Y : 1080

(언리얼 에디터-CharacterTexture) 디테일-Rander Target Format : RTF RGBA8

 

(언리얼 에디터) 액터 배치-Scene Capture 2D : Wukong 앞에 배치

(언리얼 에디터) Alt 복사 이동 : Countess 앞에 배치

(언리얼 에디터) Scene Capture -> 디테일-Scene Capture-TextureTarget : "Character Texture"

(언리얼 에디터) Scene Capture -> 디테일-Scene Capture-TextureTarget : "Character Texture"

 

(언리얼 에디터) 디테일-Primitive Render Mode : "Use ShowOnly List"

// 상황에 따라 설정

(언리얼 에디터) 디테일-Show Only Actors : "Wukong"

(언리얼 에디터) 디테일-Composite Mode : "Overwrite"

(언리얼 에디터) 디테일-Capture Source : (HDR) in RGB

// 선택된 것에 따라 이미지가 다르게 나옴.

(언리얼 에디터 )디테일-Auto Active : "해제"

 

(언리얼 에디터) 디테일-Primitive Render Mode : "Use ShowOnly List"

(언리얼 에디터) 디테일-Show Only Actors : "Countess"

(언리얼 에디터) 디테일-Composite Mode : "Overwrite"

(언리얼 에디터) 디테일-Capture Source : (HDR) in RGB

// "SceneColor(HDR) in RGB Scene Depth in A"

(언리얼 에디터) 디테일-Auto Active : "해제"

 

(언리얼 에디터) UI_CharaterState -> 디테일-Appearance-Character Texture 설정 

 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++생성 -> 부모 : "Actor " 이름 : "SelectSceneCaptureManager"

 

(언리얼 에디터) Player -> 우클릭_블루프린트클래스-부모 : "SelectSceneCaptureManger" 이름 : "BPSceneCaptureManager" -> 배치

(언리얼 에디터-BPSceneCaptureManager) 디테일-Scene Capture Array -> 2개 설정 

 

(언리얼 에디터) UI_SelectLevel  -> 사용자 생성 -> UICharacterState 배치 : "WukongCharacterStatus" 변수인지 : "체크"

// 사용자 생성으로 만든 것을 사용할 수 있음. 

 

(언리얼 에디터) UI -> 우클릭_머터리얼&텍스처-렌더타깃 : "CountessTexture"

 

(언리얼 에디터) UI_SelectLevel  -> 사용자 생성 -> UICharacterState 배치 : "CountessCharacterStatus" 변수인지 : "체크"

 

(언리얼 에디터) UI_SelectLevel  -> 그래프

 

(언리얼 에디터) UI -> 우클릭-머터리얼 : "MTCharacterTexture"

 

(언리얼 에디터) MTCharacterTexture : 설정

 

(언리얼 에디터) CuntessTexture : 디테일 -> 설정 

 

(언리얼 에디터) MTCharacterTexture -> 우클릭_머터리얼 인스턴스 생성 : "MTWukongTexture_Inst"

(언리얼 에디터) MTCharacterTexture -> 우클릭_머터리얼 인스턴스 생성 : "MTCharacterTexture_Inst"

 

(언리얼 에디터) UI_CharacterState  -> 변수인지 제거

 

(언리얼 에디터) UI_SelectLevel  -> 변수인지 제거

 

(C++-SelectGameMode.h)

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

#pragma once

#include "GameInfo.h"
#include "GameFramework/GameModeBase.h"
#include "SelectGameMode.generated.h"

/**
 * 
 */
UCLASS()
class UE7PROJECT_API ASelectGameMode : public AGameModeBase
{
    GENERATED_BODY()

public:
    ASelectGameMode();

private:
    TSubclassOf<UUserWidget> SelectLevelWidgetClass;
    class USelectLevelWidget* SelectLevelWidget;

public:
    class USelectLevelWidget* GetSelectLevelWidget() const
    {
        return SelectLevelWidget;
    }

public:
    virtual void BeginPlay();
};

(C++-SelectGameMode.cpp)

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


#include "SelectGameMode.h"
#include "SelectPlayer.h"
#include "SelectPlayerController.h"
#include "SelectLevelWidget.h"

ASelectGameMode::ASelectGameMode()
{
    DefaultPawnClass = ASelectPlayer::StaticClass();
    //PlayerControllerClass = AStartPlayerController::StaticClass();

    static ConstructorHelpers::FClassFinder<UUserWidget> SelectWidgetClass(TEXT("WidgetBlueprint'/Game/UI/UI_SelectLevel.UI_SelectLevel_C'"));

    if (SelectWidgetClass.Succeeded())
        SelectLevelWidgetClass = SelectWidgetClass.Class;
    
    static ConstructorHelpers::FClassFinder<ASelectPlayerController> ControllerClass(TEXT("Blueprint'/Game/Player/BPSelectPlayerController.BPSelectPlayerController_C'"));

    if (ControllerClass.Succeeded())
        PlayerControllerClass = ControllerClass.Class;
}

void ASelectGameMode::BeginPlay()
{
    Super::BeginPlay();

    if (IsValid(SelectLevelWidgetClass))
    {
        SelectLevelWidget = Cast<USelectLevelWidget>(CreateWidget(GetWorld(), SelectLevelWidgetClass));

        if (IsValid(SelectLevelWidget))
        {
            SelectLevelWidget->AddToViewport();
        }
    }
}

 

(C++-SelectLevelWidget.h)

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

#pragma once

#include "GameInfo.h"
#include "Blueprint/UserWidget.h"
#include "SelectLevelWidget.generated.h"

/**
 * 
 */
UCLASS()
class UE7PROJECT_API USelectLevelWidget : public UUserWidget
{
    GENERATED_BODY()

protected:
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UButton* StartButton;
    
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UButton* EndButton;

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UCharacterStateWidget* WukongStateWidget;

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UCharacterStateWidget* CountessStateWidget;

public:
    void VisibleWukong(ESlateVisibility eVisibility);
    void VisibleCountess(ESlateVisibility eVisibility);

protected:
    virtual void NativePreConstruct();
    virtual void NativeConstruct();
    virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime);

private:
    UFUNCTION(BlueprintCallable)
    void StartButtonCallback();

    UFUNCTION(BlueprintCallable)
    void EndButtonCallback();
	
};

(C++-SelectLevelWidget.cpp)

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


#include "SelectLevelWidget.h"
#include "Components/Button.h"
#include "CharacterStateWidget.h"

void USelectLevelWidget::VisibleWukong(ESlateVisibility eVisibility)
{
    WukongStateWidget->SetVisibility(eVisibility);
}

void USelectLevelWidget::VisibleCountess(ESlateVisibility eVisibility)
{
    CountessStateWidget->SetVisibility(eVisibility);
}

void USelectLevelWidget::NativePreConstruct()
{
    Super::NativePreConstruct();

    StartButton = Cast<UButton>(GetWidgetFromName(TEXT("StartButton")));
    EndButton = Cast<UButton>(GetWidgetFromName(TEXT("EndButton")));
    WukongStateWidget = Cast<UCharacterStateWidget>(GetWidgetFromName(TEXT("WukongCharacterState")));
    CountessStateWidget = Cast<UCharacterStateWidget>(GetWidgetFromName(TEXT("CountessCharacterState")));
	
    StartButton->OnClicked.AddDynamic(this, &USelectLevelWidget::StartButtonCallback);
    EndButton->OnClicked.AddDynamic(this, &USelectLevelWidget::EndButtonCallback);

    LOG(TEXT("ParentCon"));
}

void USelectLevelWidget::NativeConstruct()
{
    Super::NativeConstruct();
}

void USelectLevelWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
    Super::NativeTick(MyGeometry, InDeltaTime);
}

void USelectLevelWidget::StartButtonCallback()
{
    UGameplayStatics::OpenLevel(GetWorld(), TEXT("Main"));
}

void USelectLevelWidget::EndButtonCallback()
{
}

(C++-SelectPlalyer.h)

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

#pragma once

#include "GameInfo.h"
#include "GameFramework/Pawn.h"
#include "SelectPlayer.generated.h"

UCLASS()
class UE7PROJECT_API ASelectPlayer : public APawn
{
    GENERATED_BODY()
    
public:
    // Sets default values for this pawn's properties
    ASelectPlayer();

protected:
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
    UCapsuleComponent* Body;
    
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
    USkeletalMeshComponent* Mesh;

    UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
    FString	CharacterName;

    class USelectAnimInstance* Anim;

public:
    class USelectAnimInstance* GetAnim()
    {
        return Anim;
    }

    const FString& GetCharacterName()	const
    {
        return CharacterName;
    }

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

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

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

};

(C++-SelectPlalyer.cpp)

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


#include "SelectPlayer.h"
#include "SelectAnimInstance.h"

// Sets default values
ASelectPlayer::ASelectPlayer()
{
    // 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;

    Body = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Body"));
    Mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh"));

    SetRootComponent(Body);

    Mesh->SetupAttachment(Body);
}

// Called when the game starts or when spawned
void ASelectPlayer::BeginPlay()
{
    Super::BeginPlay();
	
    Anim = Cast<USelectAnimInstance>(Mesh->GetAnimInstance());
}

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

}

// Called to bind functionality to input
void ASelectPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

}

(C++-SelectAnimInstance.h)

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

#pragma once

#include "GameInfo.h"
#include "Animation/AnimInstance.h"
#include "SelectAnimInstance.generated.h"

UENUM(BlueprintType, Meta = (Bitflags))
enum class ESelectAnim : uint8
{
    Idle,
    Select
};

UCLASS()
class UE7PROJECT_API USelectAnimInstance : public UAnimInstance
{
    GENERATED_BODY()

public:
    USelectAnimInstance();

protected:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true", Bitmask, BitmaskEnum = "ESelectAnim"))
    uint8 AnimType;

public:
    virtual void NativeInitializeAnimation();

public:
    void ChangeAnim(ESelectAnim eAnim);

public:
    UFUNCTION()
    void AnimNotify_SelectEnd();
};

(C++-SelectAnimInstance.cpp)

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


#include "SelectAnimInstance.h"


USelectAnimInstance::USelectAnimInstance()
{
}

void USelectAnimInstance::NativeInitializeAnimation()
{
    Super::NativeInitializeAnimation();

    AnimType = (uint8)ESelectAnim::Idle;
}

void USelectAnimInstance::ChangeAnim(ESelectAnim eAnim)
{
    AnimType = (uint8)eAnim;
}

void USelectAnimInstance::AnimNotify_SelectEnd()
{
    AnimType = (uint8)ESelectAnim::Idle;
}

(C++-SelectPlayerController.h)

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

#pragma once

#include "GameInfo.h"
#include "GameFramework/PlayerController.h"
#include "SelectPlayerController.generated.h"

/**
 * 
 */
UCLASS()
class UE7PROJECT_API ASelectPlayerController : public APlayerController
{
    GENERATED_BODY()

public:
    ASelectPlayerController();

private:
    bool bLButtonDown;
    bool bRButtonDown;

private:
    virtual void BeginPlay();
    virtual void SetupInputComponent();
    virtual void PlayerTick(float DeltaTime);

public:
    void LButtonClick();
    void LButtonRelease();
    void RButtonClick();
    void RButtonRelease();

private:
    void Picking();
};

(C++-SelectPlayerController.cpp)

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


#include "SelectPlayerController.h"
#include "SelectPlayer.h"
#include "SelectAnimInstance.h"
#include "SelectGameMode.h"
#include "SelectLevelWidget.h"
#include "CharacterStateWidget.h"

ASelectPlayerController::ASelectPlayerController()
{
    bLButtonDown = false;
    bRButtonDown = false;

    bShowMouseCursor = true;

    bEnableClickEvents = false;
    bEnableTouchEvents = true;
    bEnableMouseOverEvents = true;
    bEnableTouchOverEvents = true;
}

void ASelectPlayerController::BeginPlay()
{
    Super::BeginPlay();

    FInputModeGameAndUI inputMode;
    SetInputMode(inputMode);

    InputPitchScale = 0.f;
    InputYawScale = 0.f;
    InputRollScale = 0.f;
}

void ASelectPlayerController::SetupInputComponent()
{
    Super::SetupInputComponent();

    InputComponent->BindAction(TEXT("LButton"), EInputEvent::IE_Pressed, this, &ASelectPlayerController::LButtonClick);
    InputComponent->BindAction(TEXT("LButton"), EInputEvent::IE_Released, this, &ASelectPlayerController::LButtonRelease);

    InputComponent->BindAction(TEXT("RButton"), EInputEvent::IE_Pressed, this, &ASelectPlayerController::RButtonClick);
    InputComponent->BindAction(TEXT("RButton"), EInputEvent::IE_Released, this, &ASelectPlayerController::RButtonRelease);
}

void ASelectPlayerController::PlayerTick(float DeltaTime)
{
    Super::PlayerTick(DeltaTime);

    if (bLButtonDown)
    {
        Picking();
        bLButtonDown = false;
    }
    
    if (bRButtonDown)
    {
        bRButtonDown = false;
    }
}

void ASelectPlayerController::LButtonClick()
{
    bLButtonDown = true;
}

void ASelectPlayerController::LButtonRelease()
{
    bLButtonDown = false;
}

void ASelectPlayerController::RButtonClick()
{
    bRButtonDown = true;
}

void ASelectPlayerController::RButtonRelease()
{
    bRButtonDown = false;
}

void ASelectPlayerController::Picking()
{
    FHitResult result;

    bool bHit = GetHitResultUnderCursor(ECollisionChannel::ECC_Visibility, false, result);

    if (bHit)
    {
        ASelectPlayer* SelectPlayer = Cast<ASelectPlayer>(result.GetActor());

        if (IsValid(SelectPlayer))
        {
            USelectAnimInstance* Anim = SelectPlayer->GetAnim();

            Anim->ChangeAnim(ESelectAnim::Select);

            ASelectGameMode* GameMode = Cast<ASelectGameMode>(GetWorld()->GetAuthGameMode());
            USelectLevelWidget* LevelWidget = GameMode->GetSelectLevelWidget();

            if (SelectPlayer->GetCharacterName() == TEXT("Wukong"))
            {
                LevelWidget->VisibleWukong(ESlateVisibility::SelfHitTestInvisible);
                LevelWidget->VisibleCountess(ESlateVisibility::Collapsed);
            }

            else if (SelectPlayer->GetCharacterName() == TEXT("Countess"))
            {
                LevelWidget->VisibleWukong(ESlateVisibility::Collapsed);
                LevelWidget->VisibleCountess(ESlateVisibility::SelfHitTestInvisible);
            }
        }
    }
}

(C++-CharacterStateWidget.h)

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

#pragma once

#include "GameInfo.h"
#include "Blueprint/UserWidget.h"
#include "CharacterStateWidget.generated.h"

/**
 * 
 */
UCLASS()
class UE7PROJECT_API UCharacterStateWidget : public UUserWidget
{
    GENERATED_BODY()

protected:
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UTextBlock* NameText;

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UImage* CharacterImage;

protected:
    virtual void NativeConstruct();
    virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime);

private:
    //UFUNCTION(BlueprintCallable)
    //void StartButtonCallback();

    //UFUNCTION(BlueprintCallable)
    //void EndButtonCallback();
};

(C++-CharacterStateWidget.cpp)

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


#include "CharacterStateWidget.h"
#include "Components/Image.h"
#include "Components/TextBlock.h"

void UCharacterStateWidget::NativeConstruct()
{
    Super::NativeConstruct();

    NameText = Cast<UTextBlock>(GetWidgetFromName(TEXT("NameText")));
    CharacterImage = Cast<UImage>(GetWidgetFromName(TEXT("CharacterImage")));
}

void UCharacterStateWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
    Super::NativeTick(MyGeometry, InDeltaTime);
}

(C++-SelectSceneCaptureManger.h)

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

#pragma once

#include "GameInfo.h"
#include "GameFramework/Actor.h"
#include "SelectSceneCaptureManager.generated.h"

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

protected:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    TArray<ASceneCapture2D*> SceneCaptureArray;

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

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

};

(C++-SelectSceneCaptureManger.cpp)

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


#include "SelectSceneCaptureManager.h"

// Sets default values
ASelectSceneCaptureManager::ASelectSceneCaptureManager()
{
    // 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 ASelectSceneCaptureManager::BeginPlay()
{
    Super::BeginPlay();
}

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

[ 선택한 플레이어가 게임 플레이를 하도록 설정 ]

- 선택할 때마다 선택한 정보를 저장 -

(C++-UE7GameInstance.h)

UCLASS()
class UE7PROJECT_API UUE7GameInstance : public UGameInstance
{
    GENERATED_BODY()
	
public:
    UUE7GameInstance();
    ~UUE7GameInstance();

private:
    UPROPERTY()
    UDataTable* MonsterInfoTable;

    FString SelectPlayerName;  // 선택한 플레이어의 이름을 저장할 수 있도록 선언. 
...

 

 (C++-SelectLevelWidget.h) 

...
public:
    void StartButtonEnable(bool bEnable);  // 선택했을 때 활성화가 되도록 하기 위해 설정. 
};

(C++-SelectLevelWidget.cpp)

void USelectLevelWidget::NativePreConstruct()
{
    Super::NativePreConstruct();

    StartButton = Cast<UButton>(GetWidgetFromName(TEXT("StartButton")));
    EndButton = Cast<UButton>(GetWidgetFromName(TEXT("EndButton")));
    WukongStateWidget = Cast<UCharacterStateWidget>(GetWidgetFromName(TEXT("WukongCharacterState")));
    CountessStateWidget = Cast<UCharacterStateWidget>(GetWidgetFromName(TEXT("CountessCharacterState")));
	
    StartButton->OnClicked.AddDynamic(this, &USelectLevelWidget::StartButtonCallback);
    EndButton->OnClicked.AddDynamic(this, &USelectLevelWidget::EndButtonCallback);

    StartButton->SetIsEnabled(false);  // 선택을 하지 않았을 경우 비활성화가 되도록 설정.

    LOG(TEXT("ParentCon"));
}
...
void USelectLevelWidget::StartButtonEnable(bool bEnable)
{    
    StartButton->SetIsEnabled(bEnable);
}

 

(C++-SelectPlayerController.cpp)

 

...
void ASelectPlayerController::Picking()
{
    FHitResult result;

    bool bHit = GetHitResultUnderCursor(ECollisionChannel::ECC_Visibility, false, result);

    if (bHit)
    {
        ASelectPlayer* SelectPlayer = Cast<ASelectPlayer>(result.GetActor());

        if (IsValid(SelectPlayer))
        {
            USelectAnimInstance* Anim = SelectPlayer->GetAnim();

            Anim->ChangeAnim(ESelectAnim::Select);

            ASelectGameMode* GameMode = Cast<ASelectGameMode>(GetWorld()->GetAuthGameMode());
            USelectLevelWidget* LevelWidget = GameMode->GetSelectLevelWidget();

            if (SelectPlayer->GetCharacterName() == TEXT("Wukong"))
            {
                LevelWidget->VisibleWukong(ESlateVisibility::SelfHitTestInvisible);
                LevelWidget->VisibleCountess(ESlateVisibility::Collapsed);
                LevelWidget->StartButtonEnable(true);  // StartButton 활성화. 
            }
            else if (SelectPlayer->GetCharacterName() == TEXT("Countess"))
            {
                LevelWidget->VisibleWukong(ESlateVisibility::Collapsed);
                LevelWidget->VisibleCountess(ESlateVisibility::SelfHitTestInvisible);
                LevelWidget->StartButtonEnable(true);  // StartButton 활성화. 
            }
        }
    }
}

(C++-UE7GameInstance.h)

...
    FString SelectPlayerName;

public:
    void SetSelectPlayerName(const FString& PlayerName)
    {
        SelectPlayerName = PlayerName;  // 플레이어 이름을 세팅할 수 있는 함수. 
    }
...    

 

 (C++-SelectPlayerController.cpp)

...
void ASelectPlayerController::Picking()
{
    FHitResult result;

    bool bHit = GetHitResultUnderCursor(ECollisionChannel::ECC_Visibility, false, result);

    if (bHit)
    {
        ASelectPlayer* SelectPlayer = Cast<ASelectPlayer>(result.GetActor());

        if (IsValid(SelectPlayer))
        {
            USelectAnimInstance* Anim = SelectPlayer->GetAnim();

            Anim->ChangeAnim(ESelectAnim::Select);

            ASelectGameMode* GameMode = Cast<ASelectGameMode>(GetWorld()->GetAuthGameMode());
            USelectLevelWidget* LevelWidget = GameMode->GetSelectLevelWidget();

            if (SelectPlayer->GetCharacterName() == TEXT("Wukong"))
            {
                LevelWidget->VisibleWukong(ESlateVisibility::SelfHitTestInvisible);
                LevelWidget->VisibleCountess(ESlateVisibility::Collapsed);
                LevelWidget->StartButtonEnable(true);  // StartButton 활성화. 
                
                // GameInstance에 플레이어 이름 설정. 
                // 레벨과 레벨 사이에서 정보를 공유할 때 GameInstance를 사용하는 것이 좋음.
                UUE7GameInstance* GameInst = Cast<UUE7GameInstance>(GetGameInstance());
                GameInst->SetSelectPlayerName(TEXT("Wukong"));
            }
            else if (SelectPlayer->GetCharacterName() == TEXT("Countess"))
            {
                LevelWidget->VisibleWukong(ESlateVisibility::Collapsed);
                LevelWidget->VisibleCountess(ESlateVisibility::SelfHitTestInvisible);
                LevelWidget->StartButtonEnable(true);  // StartButton 활성화. 
                
                // GameInstance에 플레이어 이름 설정. 
                // 레벨과 레벨 사이에서 정보를 공유할 때 GameInstance를 사용하는 것이 좋음.
                UUE7GameInstance* GameInst = Cast<UUE7GameInstance>(GetGameInstance());
                GameInst->SetSelectPlayerName(TEXT("Countess"));
            }
        }
    }
}

 

- 레벨 이동 정리 - 

(C++-StartLevelWidget.cpp)

...
void UStartLevelWidget::EndButtonCallback()
{
    UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);  // End를 누르면 게임을 종료하도록 설정.
}

 

(C++-SelectLevelWidget.cpp)

...
void USelectLevelWidget::EndButtonCallback()
{
    UGameplayStatics::OpenLevel(GetWorld(), TEXT("Start"));  // End를 누르면 이전 화면인 Start화면으로 가도록 설정.  
}

 

- 선택한 플레이어 정보로 플레이를 할 수 있도록 설정 - 

(C++-UE7GameInstance.h)

...
public:
    void SetSelectPlayerName(const FString& PlayerName)
    {
        SelectPlayerName = PlayerName;
    }

    UFUNCTION(BlueprintCallable)  // 블루프린트에서도 사용할 수 있게 설정.
    FString GetSelectPlayerName() const  // 플레이어의 이름을 얻어올 수 있도록 함수 설정. 
    {
        return SelectPlayerName;
    }
... 
// 디버깅용.
public:
    const FMonsterInfo* FindMonsterInfo(const FName& key) const;
};

(C++-UE7GameInstance.cpp)

...
// 디버깅용
const FMonsterInfo* UUE7GameInstance::FindMonsterInfo(const FName& key)	const
{
    if (!IsValid(MonsterInfoTable))
        return nullptr;

    return MonsterInfoTable->FindRow<FMonsterInfo>(key, TEXT(""));
}

 

(C++-MainGameMode.cpp)

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


#include "MainGameMode.h"
#include "Wukong.h"
#include "WukongController.h"
#include "UE7GameInstance.h"
#include "MainHUDWidget.h"

AMainGameMode::AMainGameMode()
{
    static ConstructorHelpers::FClassFinder<UUserWidget> MainHUDWidgetAsset(TEXT("WidgetBlueprint'/Game/UI/UI_MainHUD.UI_MainHUD_C'"));

    if (MainHUDWidgetAsset.Succeeded())
        MainHUDWidgetClass = MainHUDWidgetAsset.Class;

    UUE7GameInstance* GameInst = Cast<UUE7GameInstance>(GetGameInstance());
    
    // 선택한 플레이어의 정보를 설정. 
    if (GameInst->GetSelectPlayerName() == TEXT("Wukong"))  // Wukong을 선택한 경우. 
    {
        static ConstructorHelpers::FClassFinder<AWukong> PlayerClass(TEXT("Blueprint'/Game/Player/BPWukong.BPWukong_C'"));

        if (PlayerClass.Succeeded())
            DefaultPawnClass = PlayerClass.Class;

        static ConstructorHelpers::FClassFinder<AWukongController> ControllerClass(TEXT("Blueprint'/Game/Player/BPWukongController.BPWukongController_C'"));

        if (ControllerClass.Succeeded())
            PlayerControllerClass = ControllerClass.Class;
    }
    else if (GameInst->GetSelectPlayerName() == TEXT("Countess"))  // Countess를 선택한 경우. 
    {
        static ConstructorHelpers::FClassFinder<AWukong> PlayerClass(TEXT("Blueprint'/Game/Player/BPWukong.BPWukong_C'"));

        if (PlayerClass.Succeeded())
            DefaultPawnClass = PlayerClass.Class;

        static ConstructorHelpers::FClassFinder<AWukongController> ControllerClass(TEXT("Blueprint'/Game/Player/BPWukongController.BPWukongController_C'"));

        if (ControllerClass.Succeeded())
            PlayerControllerClass = ControllerClass.Class;
    }    
}
...

 

(C++-MainGameMode.h)

...
public:
    virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage);  // 생성자에서 실행이 되지 않으므로 InitGame()을 생성하여 사용. 
};

 

(C++-MainGameMode.cpp)

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


#include "MainGameMode.h"
#include "Wukong.h"
#include "WukongController.h"
#include "UE7GameInstance.h"
#include "MainHUDWidget.h"

AMainGameMode::AMainGameMode()
{
    static ConstructorHelpers::FClassFinder<UUserWidget> MainHUDWidgetAsset(TEXT("WidgetBlueprint'/Game/UI/UI_MainHUD.UI_MainHUD_C'"));

    if (MainHUDWidgetAsset.Succeeded())
        MainHUDWidgetClass = MainHUDWidgetAsset.Class;
}

void AMainGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage)
{
    Super::InitGame(MapName, Options, ErrorMessage);
    
    UUE7GameInstance* GameInst = Cast<UUE7GameInstance>(GetGameInstance());
    
    // 선택한 플레이어의 정보를 설정. 
    if (GameInst->GetSelectPlayerName() == TEXT("Wukong"))  // Wukong을 선택한 경우. 
    {
        static ConstructorHelpers::FClassFinder<AWukong> PlayerClass(TEXT("Blueprint'/Game/Player/BPWukong.BPWukong_C'"));

        if (PlayerClass.Succeeded())
            DefaultPawnClass = PlayerClass.Class;

        static ConstructorHelpers::FClassFinder<AWukongController> ControllerClass(TEXT("Blueprint'/Game/Player/BPWukongController.BPWukongController_C'"));

        if (ControllerClass.Succeeded())
            PlayerControllerClass = ControllerClass.Class;
    }
    else if (GameInst->GetSelectPlayerName() == TEXT("Countess"))  // Countess를 선택한 경우. 
    {
        static ConstructorHelpers::FClassFinder<AWukong> PlayerClass(TEXT("Blueprint'/Game/Player/BPWukong.BPWukong_C'"));

        if (PlayerClass.Succeeded())
            DefaultPawnClass = PlayerClass.Class;

        static ConstructorHelpers::FClassFinder<AWukongController> ControllerClass(TEXT("Blueprint'/Game/Player/BPWukongController.BPWukongController_C'"));

        if (ControllerClass.Succeeded())
            PlayerControllerClass = ControllerClass.Class;
    } 
}

// 위에 설정이 제대로 되지 않을 경우. 

(언리얼 에디터) Levels -> 우클릭_블루프린트 클래스- 부모 : "MainGameMode" 이름 : "BPMainGameMode"

 

(언리얼 에디터-BPMainGameMode) Construction Script

댓글