CharacterStats 구조체에 변수 추가
CharacterStats.h
USTRUCT(BlueprintType)
struct FCharacterStats :public FTableRowBase
{
GENERATED_BODY();
public:
FCharacterStats();
// Movement property
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Movement")
float Gravity;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Movement")
float GroundFriction;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Movement")
float AirFriction;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Movement")
float MaxAirSpeed;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Movement")
float MaxWalkSpeed;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Movement")
float MaxRunSpeed;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Movement")
float MaxFallSpeed;
// Battle property
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float MaxSuperMeter;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float SuperMeter;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float MaxBurstMeter;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float BurstMeter;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float BurstMeterGain;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float MaxBlockMeter;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float BlockMeter;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float BlockMeterGain;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float PerfectParryTick;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float DamageTakenModifier;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Battle")
float DiModifier;
// Health property
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Health")
float MaxHealth;
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Stat/Health")
float Health;
};
CharacterStats.cpp
#include "CharacterStats.h"
FCharacterStats::FCharacterStats()
: Gravity(0.0f), GroundFriction(0.0f), AirFriction(0.0f), MaxWalkSpeed(0.0f), MaxRunSpeed(0.0f), MaxFallSpeed(0.0f), MaxAirSpeed(0.0f),
MaxSuperMeter(0.0f), SuperMeter(0.0f), MaxBurstMeter(0.0f), BurstMeter(0.0f), BurstMeterGain(0.0f), MaxBlockMeter(0.0f), BlockMeter(0.0f),
BlockMeterGain(0.0f), PerfectParryTick(0.0f), DamageTakenModifier(0.0f), DiModifier(0.0f), MaxHealth(0.0f), Health(0.0f)
{
}
상태 관련 Enum Class 추가
CharacterEnum.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CharacterEnum.generated.h"
UENUM(BlueprintType)
enum class ECharacterState : uint8
{
Normal UMETA(DisplayName = "Normal"),
Hitted UMETA(DisplayName = "Hitted"),
Block UMETA(DisplayName = "Block"),
Dodge UMETA(DisplayName = "Dodge"),
AMove UMETA(DisplayName = "AMove"),
BMove UMETA(DisplayName = "BMove"),
CMove UMETA(DisplayName = "CMove"),
Grab UMETA(DisplayName = "Grab"),
Grabbed UMETA(DisplayName = "Grabbed"),
Burst UMETA(DisplayName = "Burst"),
Super UMETA(DisplayName = "Super")
};
UENUM(BlueprintType)
enum class EResistanceState : uint8
{
Normal UMETA(DisplayName = "Normal"),
HyperArmor UMETA(DisplayName = "HyperArmor"),
ProjectileArmor UMETA(DisplayName = "ProjectileArmor"),
Invulnerable UMETA(DisplayName = "Invulnerable"),
ProjectileInvulnerable UMETA(DisplayName = "ProjectileInvulnerable"),
ThrowInvulnerable UMETA(DisplayName = "ThrowInvulnerable")
};
BaseCharacter.h
//Character State
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "State", meta = (AllowPrivateAccess = "true"))
ECharacterState CurrentCharacterState;
//Character Resistance State
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "State", meta = (AllowPrivateAccess = "true"))
EResistanceState CurrentResistanceState;
BaseCharacter.cpp
ABaseCharacter::ABaseCharacter()
{
//static ConstructorHelpers::FObjectFinder<UDataTable> DataTableFinder(TEXT("/Game/Character/DataTables/DT_Stats.DT_Stats"));
//if (DataTableFinder.Succeeded())
//{
// DT=DataTableFinder.Object;
//}
CurrentCharacterState=ECharacterState::Normal;
CurrentResistanceState=EResistanceState::Normal;
}
void ABaseCharacter::InitializeStat(const FName CharacterRowName)
{
if (CharacterRowName.IsValid())
{
UE_LOG(LogTemp, Display, TEXT("CharacterRowName: %s"), *CharacterRowName.ToString());
if (FCharacterStats* TempStats=DT->FindRow<FCharacterStats>(CharacterRowName,TEXT("")))
{
Stats=*TempStats;
}
}
}
- Data Table은 에디터의 블루프린트에서 지정해서 사용하기 위해 이전에 경로로 지정하던 부분을 주석 처리
- 추가로 상태 관련 Enum class를 변수로 추가 및 초기화
- Data Table의 null 체크 조건 추가 (오류 방지)
ㅡ> null 체크 하지 않았을 경우 크래시 발생 (에디터 오픈 불가)
데이터 테이블 값 수정 및 확인
- Data Table에서 수정한 값들이 정상 초기화 되지 않음
- 플레이 상황에서도 초기화가 이뤄지지 않음
- 데이터 테이블이 정상 할당된 것으로 보아 해당 문제는 아님
- 데이터 테이블의 null 체크 이후 에디터 정상 작동
- 현재 BaseCharacter를 상속한 Beholder와 같은 자식 클래스의 생성자에서 InitializeStat이 호출되는 시점에 블루프린트에서 할당한 Data Table이 아직 할당되기 전이라서 값이 초기화 되지 않는 것으로 추정
Cactus.cpp
// Sets default values
ACactus::ACactus()
{
}
// Called when the game starts or when spawned
void ACactus::BeginPlay()
{
Super::BeginPlay();
InitializeStat("Cactus");
}
- 생성자에서 함수를 호출하게 되면 Data Table이 아직 할당되기 전이므로 정상 초기화 불가
- 위와 같이 생성자가 아닌 BeginPlay()에서 Data Table을 참조하여 값을 초기화하도록 호출 시점 변경
- 여전히 게임을 시작하기 전에는 초기화되지 않은 상태
- 게임 시작 이후에는 구조체 관련 변수들이 모두 Data Table에 작성된대로 정상 초기화 완료
정리
- 데이터 테이블의 할당을 BaseCharacter의 생성자에서 에디터에서 블루프린트를 통해 할당하는 것으로 수정
- 이 과정에서 BaseCharacter를 상속받은 Beholder, Mushroom, Cactus의 생성자에서 InitializeStat을 호출하는 시점에서는 아직 블루프린트로 할당한 Data Table이 할당되기 이전의 시점
- 따라서 InitializeStat 함수의 호출 시점을 생성자에서 BeginPlay로 옮겨준 결과 게임 시작 시 구조체 관련 변수 정상 초기화 완료
참고자료
'프로젝트 > CCFF' 카테고리의 다른 글
[Project] 미친 선인장과 분노의 버섯 - #6 구조체 추가 정의 + DataLoader Update (0) | 2025.04.02 |
---|---|
[Project] 미친 선인장과 분노의 버섯 - #5 DataLoader SubSystem (0) | 2025.04.01 |
[Project] 미친 선인장과 분노의 버섯 - #3 구조체를 활용한 변수 관리 및 데이터 테이블을 이용한 변수 초기화 (0) | 2025.03.28 |
[Project] 미친 선인장과 분노의 버섯 - #2 서버-클라이언트 구조를 고려한 피격 판정 설계 (0) | 2025.03.27 |
[Project] 미친 선인장과 분노의 버섯 - #1 격투게임 템플릿 구조 분석 (0) | 2025.03.25 |