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;
};
U가 들어간 것만이 직렬화가 된다.
모든 데이터는 직렬화를 통해서 에디터에 공개 된다.
원래 C에는 이 개념이 필요가 없었다.
C는 어떤 변수에 직접적 주소 접근이 가능하다.
이 순서대로 나열 한다. I/O가 중간에 들어간다.
인터럽트 라고 있는데. : 일시적으로 중단 시키는 변수 Sleep 이라고 있는데. 이게 대표적인 인터럽트를 강제로 발생시키는
ex) 프로그래밍을 처리해 오다가. 인터럽트가 발생을 한다. 해당 인터럽트 처리 루틴에서 점프를 해서 인터럽트를 모두 마무리를 한다. 그런다음 원래 위치로 다시 돌아와서 실행을 하는 구조 - 함수구조랑 똑같다. (그래서 함수를 소프트웨어적 인터럽트 라고 한다. 서브 루틴 이라고도 불린다)
인출(fetch stage)
과 실행(execution stage)
두 가지 단계를 반복해서 수행실행
단계를 마쳐야 한다반복적으로
인터럽트 요청이 있는지 계속해서 확인한다. 인터럽트 요청이 있어야 인터럽트 서비스 단계를 진행한다.본론으로 가보면 일반적으로 C에서 나 C++에서 문제가 될게 없다. 프로그램을 임의로 RAM의 주소로 접근할 수 있다. 그런데 C이외에 다른 언어들은 RAM주소에 접근이 불가하다.
예전에는 C를 통해서 컴파일이 고도화 될 수 없었고 프로그래머 한테 모든 권한을 열어둔 것이다.
C는 우리가 알 수 없도록 구조체를 선언 한다 (일정한 크기가 아닌) A라는 변수를 하나 선언해서 ob에 대한 사이즈 만큼 파일을 써주면 된다. (ob의 주소에 접근이 가능하게 되니까)
struct A
{
};
A ob;
C#은 프로그래머 명령을 듣지 않는다. 필요한거 가져다만 쓰라고 하고, 프로그램 자체가 관리를 한다.
C++인데 왜? 3에서는 적극적으로 활용 안하였고, 4에 들어와서 활용하기 시작 언리얼로 구현 가능한게 하나가 아니다. MS/OS/PC/Android/XBOX/ SWITCH 등등 다양한 OS가 들어간다. 그래서 주소를 직접적으로 건드리면 애초에 하드웨어 구조가 달라지니까 구조체도 달라진다. 그래서 분할 할 수가 없다. 그래서 모두가 균일한 규격으로 파일을 내보내고 I/O를 통해서 나가는 것들을 직렬화를 시켜버리자 라는 의미 어떤 것이 빌드될지 모르니까.
그럼 어떠한 데이터를 직렬화를 시켜 줄 것인가?
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
입니다. 이 지정자는 서브클래스에 상속됩니다.