목차

     

     


     

     

     
    Source
        Characters
        CAnimInstance.h .cpp
    CPlayer.h .cpp
        Utilities
        CHelper.h
    CLog.h .cpp
        Global.h
    CGameMode.h .cpp
    U2212_06.Build.cs
        U2212_06.uproject
     

     

     

     

    Player 초기 세팅하기

     


     

     

    Utilities 폴더 + Global.h 파일 가져오기

     

    Utilities 폴더 + Global.h 파일을 가져와서 재사용한다.

     

    Global.h

    더보기
    #pragma once
    
    #include "DrawDebugHelpers.h"
    
    #include "Kismet/KismetSystemLibrary.h"
    #include "Kismet/KismetMathLibrary.h"
    #include "Kismet/GameplayStatics.h"
    
    #include "Utilities/CHelpers.h"
    #include "Utilities/CLog.h"

     

    CHelpers.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    
    #define CheckTrue(x) { if(x == true) return; }
    #define CheckTrueResult(x, y) { if(x == true) return y; }
    
    #define CheckFalse(x) { if(x == false) return;}
    #define CheckFalseResult(x, y) { if(x == false) return y;}
    
    #define CheckNull(x) { if(x == nullptr) return;}
    #define CheckNullResult(x, y) { if(x == nullptr) return y;}
    
    
    #define CreateTextRender()\
    {\
    	CHelpers::CreateComponent<UTextRenderComponent>(this, &Text, "Tex", Root);\
    	Text->SetRelativeLocation(FVector(0, 0, 100));\
    	Text->SetRelativeRotation(FRotator(0, 180, 0));\
    	Text->SetRelativeScale3D(FVector(2));\
    	Text->TextRenderColor = FColor::Red;\
    	Text->HorizontalAlignment = EHorizTextAligment::EHTA_Center;\
    	Text->Text = FText::FromString(GetName().Replace(L"Default__", L""));\
    }
    
    
    class U2212_06_API CHelpers
    {
    public:
    	template<typename T>
    	static void CreateComponent(AActor* InActor, T** OutComponent, FName InName, USceneComponent* InParent = nullptr, FName InSocketName = NAME_None)
    	{
    		*OutComponent = InActor->CreateDefaultSubobject<T>(InName);
    
    		if (!!InParent)
    		{
    			(*OutComponent)->SetupAttachment(InParent, InSocketName); //이렇게 사용하면 Socket Name에 _를 사용하면 안 된다.
    
    			return;
    		}
    
    		InActor->SetRootComponent(*OutComponent);
    	}
    
    	//CreateActorComponent 추가
    	template<typename T>
    	static void CreateActorComponent(AActor* InActor, T** OutComponent, FName InName)
    	{
    		*OutComponent = InActor->CreateDefaultSubobject<T>(InName);
    	}
    
    	template<typename T>
    	static void GetAsset(T** OutObject, FString InPath)
    	{
    		ConstructorHelpers::FObjectFinder<T> asset(*InPath);
    		*OutObject = asset.Object;
    	}
    
    	template<typename T>
    	static void GetAssetDynamic(T** OutObject, FString InPath)
    	{
    		*OutObject = Cast<T>(StaticLoadObject(T::StaticClass(), nullptr, *InPath));
    	}
    
    	template<typename T>
    	static void GetClass(TSubclassOf<T>* OutClass, FString InPath)
    	{
    		ConstructorHelpers::FClassFinder<T> asset(*InPath);
    		*OutClass = asset.Class;
    	}
    
    	template<typename T>
    	static T* FindActor(UWorld* InWorld)
    	{
    		for (AActor* actor : InWorld->GetCurrentLevel()->Actors)
    		{
    			if (!!actor && actor->IsA<T>())
    				return Cast<T>(actor);
    		}
    
    		return nullptr;
    	}
    
    	template<typename T>
    	static void FindActors(UWorld* InWorld, TArray<T*>& OutActors)
    	{
    		for (AActor* actor : InWorld->GetCurrentLevel()->Actors)
    		{
    			if (!!actor && actor->IsA<T>())
    				OutActors.Add(Cast<T>(actor));
    		}
    	}
    
    	template<typename T>
    	static T* GetComponent(AActor* InActor)
    	{
    		return Cast<T>(InActor->GetComponentByClass(T::StaticClass()));
    	}
    
    	template<typename T>
    	static T* GetComponent(AActor* InActor, const FString& InName)
    	{
    		TArray<T*> components;
    		InActor->GetComponents<T>(components);
    
    		for (T* component : components)
    		{
    			if (component->GetName() == InName)
    				return component;
    		}
    
    		return nullptr;
    	}
    
    	static void AttachTo(AActor* InActor, USceneComponent* InParent, FName InSocketName)
    	{
    		InActor->AttachToComponent(InParent, FAttachmentTransformRules(EAttachmentRule::KeepRelative, true), InSocketName);
    	}
    };

     

    CLog.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    
    #define LogLine(){ CLog::Log(__FILE__, __FUNCTION__, __LINE__); }
    #define PrintLine(){ CLog::Print(__FILE__, __FUNCTION__, __LINE__); }
    
    class U2212_06_API CLog
    {
    public:
    	static void Log(int32 InValue);
    	static void Log(float InValue);
    	static void Log(const FString& InValue);
    	static void Log(const FVector& InValue);
    	static void Log(const FRotator& InValue);
    	static void Log(const UObject* InValue);
    	static void Log(const FString& InFileName, const FString& InFuncName, int32 InLineNumber);
    
    	static void Print(int32 InValue, int32 InKey = -1, float InDuration = 10, FColor InColor = FColor::Blue);
    	static void Print(float InValue, int32 InKey = -1, float InDuration = 10, FColor InColor = FColor::Blue);
    	static void Print(const FString& InValue, int32 InKey = -1, float InDuration = 10, FColor InColor = FColor::Blue);
    	static void Print(const FVector& InValue, int32 InKey = -1, float InDuration = 10, FColor InColor = FColor::Blue);
    	static void Print(const FRotator& InValue, int32 InKey = -1, float InDuration = 10, FColor InColor = FColor::Blue);
    	static void Print(const UObject* InValue, int32 InKey = -1, float InDuration = 10, FColor InColor = FColor::Blue);
    	static void Print(const FString& InFileName, const FString& InFuncName, int32 InLineNumber);
    };

     

    CLog.cpp

    더보기
    #include "Utilities/CLog.h"
    #include "Engine.h"
    
    DEFINE_LOG_CATEGORY_STATIC(GP, Display, All)
    
    void CLog::Log(int32 InValue)
    {
    	//GLog->Log("GP", ELogVerbosity::Display, FString::FromInt(InValue));
    	UE_LOG(GP, Display, L"%d", InValue);
    }
    
    void CLog::Log(float InValue)
    {
    	UE_LOG(GP, Display, L"%f", InValue);
    }
    
    void CLog::Log(const FString & InValue)
    {
    	UE_LOG(GP, Display, L"%s", *InValue);
    }
    
    void CLog::Log(const FVector & InValue)
    {
    	UE_LOG(GP, Display, L"%s", *InValue.ToString());
    }
    
    void CLog::Log(const FRotator & InValue)
    {
    	UE_LOG(GP, Display, L"%s", *InValue.ToString());
    }
    
    void CLog::Log(const UObject * InValue)
    {
    	FString str;
    
    	if (!!InValue)
    		str.Append(InValue->GetName());
    
    	str.Append(!!InValue ? " Not Null" : "Null");
    
    	UE_LOG(GP, Display, L"%s", *str);
    }
    
    void CLog::Log(const FString & InFileName, const FString & InFuncName, int32 InLineNumber)
    {
    	//C:\\Test\\Test.cpp
    
    	int32 index = 0, length = 0;
    	InFileName.FindLastChar(L'\\', index);
    
    	length = InFileName.Len() - 1;
    	FString fileName = InFileName.Right(length - index);
    
    	UE_LOG(GP, Display, L"%s, %s, %d", *fileName, *InFuncName, InLineNumber);
    }
    
    void CLog::Print(int32 InValue, int32 InKey, float InDuration, FColor InColor)
    {
    	GEngine->AddOnScreenDebugMessage(InKey, InDuration, InColor, FString::FromInt(InValue));
    }
    
    void CLog::Print(float InValue, int32 InKey, float InDuration, FColor InColor)
    {
    	GEngine->AddOnScreenDebugMessage(InKey, InDuration, InColor, FString::SanitizeFloat(InValue));
    }
    
    void CLog::Print(const FString & InValue, int32 InKey, float InDuration, FColor InColor)
    {
    	GEngine->AddOnScreenDebugMessage(InKey, InDuration, InColor, InValue);
    }
    
    void CLog::Print(const FVector & InValue, int32 InKey, float InDuration, FColor InColor)
    {
    	GEngine->AddOnScreenDebugMessage(InKey, InDuration, InColor, InValue.ToString());
    }
    
    void CLog::Print(const FRotator & InValue, int32 InKey, float InDuration, FColor InColor)
    {
    	GEngine->AddOnScreenDebugMessage(InKey, InDuration, InColor, InValue.ToString());
    }
    
    void CLog::Print(const UObject * InValue, int32 InKey, float InDuration, FColor InColor)
    {
    	FString str;
    
    	if (!!InValue)
    		str.Append(InValue->GetName());
    
    	str.Append(!!InValue ? " Not Null" : "Null");
    
    	GEngine->AddOnScreenDebugMessage(InKey, InDuration, InColor, str);
    }
    
    void CLog::Print(const FString& InFileName, const FString& InFuncName, int32 InLineNumber)
    {
    	int32 index = 0, length = 0;
    	InFileName.FindLastChar(L'\\', index);
    
    	length = InFileName.Len() - 1;
    	FString fileName = InFileName.Right(length - index);
    
    	FString str = FString::Printf(L"%s, %s, %d", *fileName, *InFuncName, InLineNumber);
    	GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Blue, str);
    }

     

     

    CPlayer + BP_CPlayer 생성하기

     

    새 C++ 생성하기 -  Character - CPlayer 생성

     

    CPlayer.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Character.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;
    
    public:
    	ACPlayer();
    
    protected:
    	virtual void BeginPlay() override;
    
    public:	
    	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    
    };

     

     

     

    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"
    
    ACPlayer::ACPlayer()
    {
    	CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetMesh());
    	CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);
    
    	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();
    	
    }
    
    void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
    	Super::SetupPlayerInputComponent(PlayerInputComponent);
    
    }

     

     

     

     

    BP_CPlayer

    새 C++ 클래스 생성 - (방금 전에 생성한) CPlayer -  

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     


     

    CGameMode 생성

     

    U_06GameModeBase를 CGameMode로 이름변경

     

    CGameMode.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/GameModeBase.h"
    #include "CGameMode.generated.h"
    
    UCLASS()
    class U2212_06_API ACGameMode : public AGameModeBase
    {
    	GENERATED_BODY()
    
    public:
    	ACGameMode();
    };

     

     

     

    CGameMode.cpp

    더보기
    #include "CGameMode.h"
    #include "Global.h"
    
    ACGameMode::ACGameMode()
    {
    	CHelpers::GetClass<APawn>(&DefaultPawnClass, "Blueprint'/Game/Player/BP_CPlayer.BP_CPlayer_C'");
    }

     

     

     

    프로젝트 세팅 - 맵&모드 - Default Modes - 기본 게임모드 - CGameMode로 변경

     


     

     

    CAnimInstance + ABP_Character 생성

     

    새 C++ 클래스 - AnimInstance - CAnimInstance 생성

     

     

    CAnimInstance.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "Animation/AnimInstance.h"
    #include "CAnimInstance.generated.h"
    
    UCLASS()
    class U2212_06_API UCAnimInstance : public UAnimInstance
    {
    	GENERATED_BODY()
    
    protected:
        UPROPERTY(BlueprintReadOnly, Category = "Animation")
            float Speed;
    
        UPROPERTY(BlueprintReadOnly, Category = "Animation")
            float Pitch;
    
        UPROPERTY(BlueprintReadOnly, Category = "Animation")
            float Direction;
    
    public:
        void NativeBeginPlay() override;
        void NativeUpdateAnimation(float DeltaSeconds) override;
    
    private:
        class ACharacter* OwnerCharacter;
    
    private:
        FRotator PrevRotation;
    };

     

     

     

    CAnimInstance.cpp

    더보기
    #include "Characters/CAnimInstance.h"
    #include "Global.h"
    #include "GameFramework/Character.h"
    
    void UCAnimInstance::NativeBeginPlay()
    {
    	Super::NativeBeginPlay();
    
    	OwnerCharacter = Cast<ACharacter>(TryGetPawnOwner());
    	CheckNull(OwnerCharacter);
    
    }
    
    void UCAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
    {
    	Super::NativeUpdateAnimation(DeltaSeconds);
    	CheckNull(OwnerCharacter);
    
    	Speed = OwnerCharacter->GetVelocity().Size2D();
    
    	FRotator rotator = OwnerCharacter->GetVelocity().ToOrientationRotator();
    	FRotator rotator2 = OwnerCharacter->GetControlRotation();
    	FRotator delta = UKismetMathLibrary::NormalizedDeltaRotator(rotator, rotator2);
    	PrevRotation = UKismetMathLibrary::RInterpTo(PrevRotation, delta, DeltaSeconds, 25);
    	Direction = PrevRotation.Yaw;
    
    	Pitch = UKismetMathLibrary::FInterpTo(Pitch, OwnerCharacter->GetBaseAimRotation().Pitch, DeltaSeconds, 25);
    }

     

     

     

    애니메이션 - 애니메이션 블루프린트 - ABP_Character 생성

     

     

     

     


     

     

     

    실행화면