aim 설정값 관리

CAim (여기서 한꺼번에 관리 해줄 것 아래 2개를 )

CAim_Third(3인칭)

CAim_First(1인칭)

CAim_Third.h — 필요한거 override 더이상 자식으로 상속 안 줄 때는 자식으로 안내려갈 함수는 virtual로 뺴버리는 것

#pragma once

#include "CoreMinimal.h"
#include "05_TPS/CAim.h" //상속
#include "CAim_Third.generated.h"

//Third에서 구조체 만들고 멤버로 소속하고 블루프린트 화 되면 구조체의 값을 수정 할 수 있게 
USTRUCT()
struct FAimData
{
	GENERATED_BODY()
		
public:
	UPROPERTY(EditDefaultsOnly)
		float TargetArmLength = 100;
	
};
/////////////////////////////
UCLASS(Blueprintable)
class U2110_03_API UCAim_Third : public UCAim
{
	GENERATED_BODY()
	
private:
	UPROPERTY(EditDefaultsOnly, Category = "Aim")
		FAimData AimData;

	//만약이곳에 int Test= 10 넣으면 블프에서 나타나지 않는다 직렬화 되지 못하니까.

public:	
	UCAim_Third();

	void BeginPlay(class ACharacter* InCharacter, class ACRifle* InRifle) override; //override 붙여주기
	void Tick(float DeltaTime) override;

	bool IsAvaliableZoom() override; //zoom가능한지 체크 

	void Begin_Aim() override;
	void End_Aim() override;

private:
	UFUNCTION() //직접 콜 될때만 델리게이션 처리 
		void Zooming(float Output) override;

private:
	class USpringArmComponent* SpringArm;
	class UCameraComponent* Camera;
};

Untitled

U가 들어간 것만이 직렬화가 된다.

중요)

모든 데이터는 직렬화를 통해서 에디터에 공개 된다.

원래 C에는 이 개념이 필요가 없었다.

C는 어떤 변수에 직접적 주소 접근이 가능하다.

FT_2022-06-21 11_13_04.177.png

이 순서대로 나열 한다. I/O가 중간에 들어간다.

Untitled

인터럽트 라고 있는데. : 일시적으로 중단 시키는 변수 Sleep 이라고 있는데. 이게 대표적인 인터럽트를 강제로 발생시키는

ex) 프로그래밍을 처리해 오다가. 인터럽트가 발생을 한다. 해당 인터럽트 처리 루틴에서 점프를 해서 인터럽트를 모두 마무리를 한다. 그런다음 원래 위치로 다시 돌아와서 실행을 하는 구조 - 함수구조랑 똑같다. (그래서 함수를 소프트웨어적 인터럽트 라고 한다. 서브 루틴 이라고도 불린다)

Untitled

Untitled

본론으로 가보면 일반적으로 C에서 나 C++에서 문제가 될게 없다. 프로그램을 임의로 RAM의 주소로 접근할 수 있다. 그런데 C이외에 다른 언어들은 RAM주소에 접근이 불가하다.

언리얼에서는 왜 ? 직렬화 라는 개념을 도입 했을까?

C++인데 왜? 3에서는 적극적으로 활용 안하였고, 4에 들어와서 활용하기 시작 언리얼로 구현 가능한게 하나가 아니다. MS/OS/PC/Android/XBOX/ SWITCH 등등 다양한 OS가 들어간다. 그래서 주소를 직접적으로 건드리면 애초에 하드웨어 구조가 달라지니까 구조체도 달라진다. 그래서 분할 할 수가 없다. 그래서 모두가 균일한 규격으로 파일을 내보내고 I/O를 통해서 나가는 것들을 직렬화를 시켜버리자 라는 의미 어떤 것이 빌드될지 모르니까.

그럼 어떠한 데이터를 직렬화를 시켜 줄 것인가?

Untitled

UPROPERTY~ UINTERFACE

ex) 선언만 해서 블루프린트에 공개 될 수 없다 (직렬화가 되지 않는 클래스)

class A //이런거 는 UPROPERTY가 들어가도 직렬화 할 수 없다.
{

};

그래서 직렬화 할려면 GENERATED_BODY()가 들어가야하고 직렬화에 대한 내용은 헤더에 들어가 있다.

UCLASS() //직렬화에 대한 내용이 들어가야 한다. 그게 GENERATED_BODY()이다 
class A 
{
//클래스 A에 대한 객체에서 int a는 직렬화가 될 수 있다. 
	UPROPERTY
			int a;
	
	int b; //직렬화 할 때 이것은 버려지는 것이다. (함수도 마찬가지) 
};

그래서 직렬화가 가능한 애만 에디터에 사용할 수 있다. 별개의 모듈이라서 공개해야 해서. UPROPERTY같이 직렬화를 통해 공개가 된다. (직렬화, 역직렬화)

USTRUCT도 마찬가지 이다. 구조체를 직렬화를 만나게 해주어야 하고, 필요한 것들만 UFUNTION이 가 되어야 한다.

그런데 언리얼에서는 구조체와 클래스를 구분해서 사용한다.

CAim_Third.cpp

#include "CAim_Third.h"
#include "Global.h"
#include "GameFramework/Character.h" //GetComponent
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"

UCAim_Third::UCAim_Third()
{
 

}

void UCAim_Third::BeginPlay( ACharacter* InCharacter,  ACRifle* InRifle)
{
	Super::BeginPlay(InCharacter, InRifle);
	
	SpringArm = CHelpers::GetComponent<USpringArmComponent>(OwnerCharacter);
	Camera = CHelpers::GetComponent<UCameraComponent>(OwnerCharacter);

}

void UCAim_Third::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

bool UCAim_Third::IsAvaliableZoom()
{

	Super::IsAvaliableZoom();

	return !!SpringArm && !!Camera; //springarm과 camera가 NULL이 아니여야 한다. 
}

void UCAim_Third::Begin_Aim()
{
	Super::Begin_Aim();

	CheckFalse(IsAvaliableZoom());

}

void UCAim_Third::End_Aim()
{
	Super::End_Aim();

}

void UCAim_Third::Zooming(float Output)
{
	Super::Zooming(Output);
}

CAim.h

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "CAim.generated.h"

UCLASS(Abstract)
class U2110_03_API UCAim : public UObject 
{
	GENERATED_BODY()

public:
	FORCEINLINE bool IsAiming() { return bAiming; }

public:
	UCAim();

public:
	//Begin에서 Acharacter과 Rifle 넣어주기
	virtual void BeginPlay(class ACharacter* InCharacter, class ACRifle* InRifle); //Tick하고beginplay없어도 미리 만듬
	virtual void Tick(float DeltaTime) { } //tick도 외부에서 사용 할 수 있고 자식들에게 재정의 가능 

	virtual bool IsAvaliableZoom() { return false; } //Zoom이 가능한가 체크 할 것

	virtual void Begin_Aim() { }
	virtual void End_Aim() { }

protected: //자식에서 접근 
	virtual void Zooming (float Output) { }

protected:
	class ACharacter* OwnerCharacter;
	class ACRifle* Rifle;

	bool bAiming;
};

여긴 Tick이 없다.

CAim.cpp

#include "CAim.h"
#include "Global.h"

UCAim::UCAim()
{

}

void UCAim::BeginPlay(ACharacter* InCharacter, ACRifle* InRifle)
{
	OwnerCharacter = InCharacter; //owner받아오고 
	Rifle = InRifle;

}

UCLASS안에

Blueprintable : 이걸 넣으면 이 클래스가 블루프린트화가 가능 해진다는 것

BlueprintType : 블루프린트 쪽에서 변수타입을 다룰 수 있다

Unreal Document 클래스 지정자

Abstract

순수 가상 함수를 추가할 때?

블프 만드는 것이 막힌다?

추상 클래스로 사용하겠다는 의미 이 키워드가 들어가면 객체화 해서 사용할 수 없다.

자식에서 재정의 해라 하면. 블루프린트 뭐시기 해서 콜해줘도 된다.

Abstract (추상) 지정자는 클래스를 "추상 베이스 클래스" 로 선언하여, 사용자가 이 클래스 액터를 월드에 추가하지 못하도록 합니다. 그 자체로는 의미가 없는 클래스에 쓰기 좋습니다. 예를 들어 ATriggerBase 베이스 클래스는 추상형이라도 그 서브클래스 ATriggerBox 가 추상형이 아니라면 레벨에 배치할 수 있습니다.

Blueprintable

이 클래스를 블루프린트 생성이 가능한 베이스 클래스로 노출시킵니다. 기본값은 다른 식으로 상속되지 않는 한 NotBlueprintable 입니다. 이 지정자는 서브클래스에 상속됩니다.