목차

     

     


     

     

     
    Source
        Characters
        CAnimInstance.h .cpp
    CPlayer.h .cpp
        Components
        CMontagesComponent.h .cpp .생성
    CMovementComponent.h .cpp 생성
    CStateComponent.h .cpp 생성
    CWeaponComponent.h .cpp 생성
        Utilities
        CHelper.h
    CLog.h .cpp
        Global.h
    CGameMode.h .cpp
    U2212_06.Build.cs
        U2212_06.uproject
     

     

     

    Component 만들기 (Movement, State, Montage)

     

     


     

    CMovementComponent 생성

     

    새 C++ 클래스 - ActorComponent - CMovementComponent 생성

     

    CMovementComponent.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Components/ActorComponent.h"
    #include "CMovementComponent.generated.h"
    UENUM()
    enum class ESpeedType : uint8
    {
    Walk = 0, Run, Sprint, Max,
    };
    UCLASS()
    class U2212_06_API UCMovementComponent : public UActorComponent
    {
    GENERATED_BODY()
    private:
    UPROPERTY(EditAnywhere, Category = "CameraSpeed")
    float HorizontalLook = 45;
    UPROPERTY(EditAnywhere, Category = "CameraSpeed")
    float VerticalLook = 45;
    private:
    UPROPERTY(EditAnywhere, Category = "Speed")
    float Speed[(int32)ESpeedType::Max] = { 200, 400, 600 };
    public:
    FORCEINLINE bool CanMove() { return bCanMove; }
    FORCEINLINE void Move() { bCanMove = true; }
    FORCEINLINE void Stop() { bCanMove = false; }
    FORCEINLINE float GetWalkSpeed() { return Speed[(int32)ESpeedType::Walk]; }
    FORCEINLINE float GetRunSpeed() { return Speed[(int32)ESpeedType::Run]; }
    FORCEINLINE float GetSprintSpeed() { return Speed[(int32)ESpeedType::Sprint]; }
    FORCEINLINE bool GetFixedCamera() { return bFixedCamera; }
    FORCEINLINE void EnableFixedCamera() { bFixedCamera = true; }
    FORCEINLINE void DisableFixedCamera() { bFixedCamera = false; }
    public:
    UCMovementComponent();
    protected:
    virtual void BeginPlay() override;
    private:
    void SetSpeed(ESpeedType InType);
    public:
    void OnSprint();
    void OnRun();
    void OnWalk();
    void EnableControlRotation();
    void DisableControlRotation();
    public:
    void OnMoveForward(float InAxis);
    void OnMoveRight(float InAxis);
    void OnHorizontalLook(float InAxis);
    void OnVerticalLook(float InAxis);
    private:
    class ACharacter* OwnerCharacter;
    private:
    bool bCanMove = true; //이동할 수 있는가
    bool bFixedCamera; //카메라 고정인가
    };

     

     

     

    CMovementComponent.cpp

    더보기
    #include "Components/CMovementComponent.h"
    #include "Global.h"
    #include "GameFramework/Character.h"
    #include "GameFramework/CharacterMovementComponent.h"
    UCMovementComponent::UCMovementComponent()
    {
    }
    void UCMovementComponent::BeginPlay()
    {
    Super::BeginPlay();
    OwnerCharacter = Cast<ACharacter>(GetOwner());
    }
    void UCMovementComponent::SetSpeed(ESpeedType InType)
    {
    OwnerCharacter->GetCharacterMovement()->MaxWalkSpeed = Speed[(int32)InType];
    }
    void UCMovementComponent::OnSprint()
    {
    SetSpeed(ESpeedType::Sprint);
    }
    void UCMovementComponent::OnRun()
    {
    SetSpeed(ESpeedType::Run);
    }
    void UCMovementComponent::OnWalk()
    {
    SetSpeed(ESpeedType::Walk);
    }
    void UCMovementComponent::EnableControlRotation()
    {
    OwnerCharacter->bUseControllerRotationYaw = true;
    OwnerCharacter->GetCharacterMovement()->bOrientRotationToMovement = false;
    }
    void UCMovementComponent::DisableControlRotation()
    {
    OwnerCharacter->bUseControllerRotationYaw = false;
    OwnerCharacter->GetCharacterMovement()->bOrientRotationToMovement = true;
    }
    void UCMovementComponent::OnMoveForward(float InAxis)
    {
    CheckFalse(bCanMove);
    FRotator rotator = FRotator(0, OwnerCharacter->GetControlRotation().Yaw, 0);
    FVector direction = FQuat(rotator).GetForwardVector();
    OwnerCharacter->AddMovementInput(direction, InAxis);
    }
    void UCMovementComponent::OnMoveRight(float InAxis)
    {
    CheckFalse(bCanMove);
    FRotator rotator = FRotator(0, OwnerCharacter->GetControlRotation().Yaw, 0);
    FVector direction = FQuat(rotator).GetRightVector();
    OwnerCharacter->AddMovementInput(direction, InAxis);
    }
    void UCMovementComponent::OnHorizontalLook(float InAxis)
    {
    CheckTrue(bFixedCamera);
    OwnerCharacter->AddControllerYawInput(InAxis * HorizontalLook * GetWorld()->GetDeltaSeconds());
    }
    void UCMovementComponent::OnVerticalLook(float InAxis)
    {
    CheckTrue(bFixedCamera);
    OwnerCharacter->AddControllerPitchInput(InAxis * VerticalLook * GetWorld()->GetDeltaSeconds());
    }

     

     


     

     

    CStateComponent 생성

     

    새 C++ 클래스 - ActorComponent - CStateComponent 생성

     

    CStateComponent.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Components/ActorComponent.h"
    #include "CStateComponent.generated.h"
    UENUM()
    enum class EStateType : uint8
    {
    Idle = 0, BackStep, Equip, Hitted, Dead, Action, Max,
    };
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FStateTypeChanged, EStateType, InPrevType, EStateType, InNewType);
    UCLASS()
    class U2212_06_API UCStateComponent : public UActorComponent
    {
    GENERATED_BODY()
    public:
    FORCEINLINE bool IsIdleMode() { return Type == EStateType::Idle; }
    FORCEINLINE bool IsBackstepMode() { return Type == EStateType::BackStep; }
    FORCEINLINE bool IsEquipMode() { return Type == EStateType::Equip; }
    FORCEINLINE bool IsHittedMode() { return Type == EStateType::Hitted; }
    FORCEINLINE bool IsDeadMode() { return Type == EStateType::Dead; }
    FORCEINLINE bool IsActionMode() { return Type == EStateType::Action; }
    public:
    UCStateComponent();
    protected:
    virtual void BeginPlay() override;
    public:
    void SetIdleMode();
    void SetBackStepMode();
    void SetEquipMode();
    void SetHittedMode();
    void SetDeadMode();
    void SetActionMode();
    private:
    void ChangeType(EStateType InType);
    public:
    FStateTypeChanged OnStateTypeChanged;
    private:
    EStateType Type;
    };

     

     

     

    CStateComponent.cpp

    더보기
    #include "Components/CStateComponent.h"
    #include "Global.h"
    UCStateComponent::UCStateComponent()
    {
    }
    void UCStateComponent::BeginPlay()
    {
    Super::BeginPlay();
    }
    void UCStateComponent::SetIdleMode()
    {
    ChangeType(EStateType::Idle);
    }
    void UCStateComponent::SetBackStepMode()
    {
    ChangeType(EStateType::BackStep);
    }
    void UCStateComponent::SetEquipMode()
    {
    ChangeType(EStateType::Equip);
    }
    void UCStateComponent::SetHittedMode()
    {
    ChangeType(EStateType::Hitted);
    }
    void UCStateComponent::SetDeadMode()
    {
    ChangeType(EStateType::Dead);
    }
    void UCStateComponent::SetActionMode()
    {
    ChangeType(EStateType::Action);
    }
    void UCStateComponent::ChangeType(EStateType InType)
    {
    EStateType prevType = Type;
    Type = InType;
    if (OnStateTypeChanged.IsBound())
    OnStateTypeChanged.Broadcast(prevType, Type);
    }

     

     

     


     

     

     

    CMontageComponent 생성

     

    새 C++ 클래스 - ActorComponent - CMontageComponent 생성

     

     CMontageComponent .h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Components/ActorComponent.h"
    #include "Components/CStateComponent.h"
    #include "Engine/DataTable.h"
    #include "CMontagesComponent.generated.h"
    USTRUCT()
    struct FMontageData
    : public FTableRowBase
    {
    GENERATED_BODY()
    public:
    UPROPERTY(EditAnywhere)
    EStateType Type; //상태 Type
    UPROPERTY(EditAnywhere)
    class UAnimMontage* Montage;
    UPROPERTY(EditAnywhere)
    float PlayRate = 1; //Player 속도
    };
    UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
    class U2212_06_API UCMontagesComponent : public UActorComponent
    {
    GENERATED_BODY()
    private:
    UPROPERTY(EditAnywhere, Category = "DataTable")
    UDataTable* DataTable;
    public:
    UCMontagesComponent();
    protected:
    virtual void BeginPlay() override;
    public:
    void PlayBackStepMode();
    private:
    void PlayAnimMontage(EStateType InType);
    private:
    class ACharacter* OwnerCharacter;
    FMontageData* Datas[(int32)EStateType::Max];
    };

     

     

     

     CMontageComponent .cpp

    더보기
    #include "Components/CMontagesComponent.h"
    #include "Global.h"
    #include "GameFramework/Character.h"
    UCMontagesComponent::UCMontagesComponent()
    {
    }
    void UCMontagesComponent::BeginPlay()
    {
    Super::BeginPlay();
    if(DataTable == nullptr)//DataTable이 없다면
    { //DataTable이 없다고 메시지를 띄워준다.
    GLog->Log(ELogVerbosity::Error, "DataTable is not selected");
    return;
    }
    OwnerCharacter = Cast<ACharacter>(GetOwner());
    TArray<FMontageData*> datas;
    DataTable->GetAllRows<FMontageData>("", datas);//전체 데이터를 가져온다.
    //가져온 데이터를 배열에 넣어준다.
    for (int32 i = 0; i< (int32)EStateType::Max; i++)
    {
    for(FMontageData* data : datas)
    {
    if((EStateType)i == data->Type)
    {
    Datas[i] = data;
    continue;
    }
    }//for(data)
    }//for(i)
    }
    //#define LOG_UCMontagesComponent 1
    #if LOG_UCMontagesComponent
    for (FMontagesData* data : datas)
    {
    if (data == nullptr)
    continue;
    FString str;
    //Static이 붙는 애들은 Reflection(자료형의 타입을 변수로 다룰 수 있게 해준다).
    str.Append(StaticEnum<EStateType>()->GetValueAsString(data->Type));//Enum을 문자열로 바꾸어서 자료형의 이름을 가져온다.
    str.Append(" / ");
    str.Append(data->Montage->GetPathName());
    CLog::Log(str);
    }
    #endif
    void UCMontagesComponent::PlayBackStepMode()
    {
    PlayAnimMontage(EStateType::BackStep);
    }
    void UCMontagesComponent::PlayAnimMontage(EStateType InType)
    {
    CheckNull(OwnerCharacter);
    FMontageData* data = Datas[(int32)InType];
    if(data == nullptr || data->Montage == nullptr)
    {
    GLog->Log(ELogVerbosity::Error, "None montages data");
    return;
    }
    OwnerCharacter->PlayAnimMontage(data->Montage, data->PlayRate);//data의 몽타주를 PlayRate속도로 OwnerCharacter에 적용하여 재생.
    }

     

     


     

     

    CPlayer 생성

     

    CPlayer.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Character.h"
    #include "Components/CStateComponent.h"
    #include "CPlayer.generated.h"
    UCLASS()
    class U2212_06_API ACPlayer : public ACharacter
    {
    GENERATED_BODY()
    private:
    UPROPERTY(VisibleAnywhere)
    class USpringArmComponent* SpringArm;
    UPROPERTY(VisibleAnywhere)
    class UCameraComponent* Camera;
    private:
    UPROPERTY(VisibleAnywhere)
    class UCMontagesComponent* Montages;
    UPROPERTY(VisibleAnywhere)
    class UCMovementComponent* Movement;
    UPROPERTY(VisibleAnywhere)
    class UCStateComponent* State;
    public:
    ACPlayer();
    protected:
    virtual void BeginPlay() override;
    public:
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    private:
    UFUNCTION()
    void OnStateTypeChanged(EStateType InPrevType, EStateType InNewType);
    private:
    void OnAvoid();
    private:
    void BackStep();
    };

     

     

    CPlayer.cpp

    더보기
    #include "Characters/CPlayer.h"
    #include "Global.h"
    #include "CAnimInstance.h"
    #include "GameFramework/SpringArmComponent.h"
    #include "GameFramework/CharacterMovementComponent.h"
    #include "Camera/CameraComponent.h"
    #include "Components/SkeletalMeshComponent.h"
    #include "Components/InputComponent.h"
    #include "Components/CMontagesComponent.h"
    #include "Components/CMovementComponent.h"
    ACPlayer::ACPlayer()
    {
    CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetMesh());
    CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);
    CHelpers::CreateActorComponent<UCMontagesComponent>(this, &Montages, "Montage");
    CHelpers::CreateActorComponent<UCMovementComponent>(this, &Movement, "Movement");
    CHelpers::CreateActorComponent<UCStateComponent>(this, &State, "State");
    GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
    GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));
    USkeletalMesh* mesh;
    CHelpers::GetAsset<USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
    GetMesh()->SetSkeletalMesh(mesh);
    TSubclassOf<UCAnimInstance> animInstance;
    CHelpers::GetClass<UCAnimInstance>(&animInstance, "AnimBlueprint'/Game/ABP_Character.ABP_Character_C'");
    GetMesh()->SetAnimClass(animInstance);
    SpringArm->SetRelativeLocation(FVector(0, 0, 140));
    SpringArm->SetRelativeRotation(FRotator(0, 90, 0));
    SpringArm->TargetArmLength = 200;
    SpringArm->bDoCollisionTest = false;
    SpringArm->bUsePawnControlRotation = true;
    SpringArm->bEnableCameraLag = true;
    GetCharacterMovement()->RotationRate = FRotator(0, 720, 0);
    }
    void ACPlayer::BeginPlay()
    {
    Super::BeginPlay();
    Movement->OnRun(); //Movement의 기본을 Run으로 설정
    Movement->DisableControlRotation();//Movement의 기본을 DisableControlRotation으로 설정
    State->OnStateTypeChanged.AddDynamic(this, &ACPlayer::OnStateTypeChanged);
    }
    void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
    Super::SetupPlayerInputComponent(PlayerInputComponent);
    PlayerInputComponent->BindAxis("MoveForward", Movement, &UCMovementComponent::OnMoveForward);
    PlayerInputComponent->BindAxis("MoveRight", Movement, &UCMovementComponent::OnMoveRight);
    PlayerInputComponent->BindAxis("VerticalLook", Movement, &UCMovementComponent::OnVerticalLook);
    PlayerInputComponent->BindAxis("HorizontalLook", Movement, &UCMovementComponent::OnHorizontalLook);
    PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Pressed, Movement, &UCMovementComponent::OnSprint);
    PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Released, Movement, &UCMovementComponent::OnRun);
    PlayerInputComponent->BindAction("Avoid", EInputEvent::IE_Pressed, this, &ACPlayer::OnAvoid);
    }
    void ACPlayer::OnStateTypeChanged(EStateType InPrevType, EStateType InNewType)
    {
    switch (InNewType)
    {
    case EStateType::BackStep: BackStep(); break;
    }
    }
    void ACPlayer::OnAvoid()
    {
    CheckFalse(State->IsIdleMode());
    CheckFalse(Movement->CanMove());
    CheckTrue(InputComponent->GetAxisValue("MoveForward") >= 0.0f);//뒷방향을 입력했다면
    State->SetBackStepMode();//State을 BackStepMode로 변경한다.
    }
    void ACPlayer::BackStep()
    {
    Movement->EnableControlRotation();//정면을 바라본 상태로 뒤로 뛰어야하기 때문에 EnableControlRotation으로 만들어준다.
    Montages->PlayBackStepMode();//PlayBackStepMode()를 통해 몽타주 재생.
    }

     

     


     

     

    이론 설명

     


     

    UCLASS 접근을 제한하는 방법

     

    • 열어두면 기획이나 디자이너가 접근하여 수정할 수 있다.  

    • 프로그래머만 접근할 수 있다.

     

     

    원격 빌드 원리

     

    CI, CD, CD 

    DevOps

     

     

    Jenkins    ←    Repo

                              ↑ push

                           소스(clinet)   원격빌드

     

     


     

     

     

     

    언리얼 에디터 상에서의 작업

     


     

     

     

    StepBack 몽타주 생성

     


     

     

     

     

    DT_Player (csv. 파일 + DataTable 만들기)

     

    액셀로 csv 파일을 만들어 DT_Player라고 이름 짓고 저장한다.

    • 첫번째 열에 인덱스 숫자 기입
    • 두번재 열에 Type 이름 넣기 (여기서는 BackStep)
    • 세번째 열에 언리얼 내에 저장된 Montage를 레퍼런스 복사하여 넣는다.
    • 네번째 열에 PlayRate(재생속도)를 기입한다.

     

     

     

    DT_Player 

     


     

     

    ABP_Player

     

    AnimGraph

     

     


     

     

     

    실행화면 - Stepback