게임을 시작하고 내가 원하는대로 안될 때 정말 답답하다. 이 때 어디서 무엇을 고쳐야 할 지 찾아보도록하자.
발단은 내가 소환한 아이템중 코인아이템을 전부 다 먹으면 다음 스테이지로 넘어가게 설계를 하였는데 코인을 다 먹어도 이동하지 않는것이다. 여기서 뭐가 문제인지 찾아봐야하는데 아직 나에게는 너무 복잡하고 많은 코드들 중 뭐가 문제인지 찾기가 쉽지 않았다.
문제의 코드 차트
#include "CH_GameState.h"
#include "Kismet/GameplayStatics.h"
#include "SpawnVolume.h"
#include "CH_GameInstance.h"
#include "CoinItem.h"
ACH_GameState::ACH_GameState()
{
Score = 0;
SpawnedCoinCount = 0;
CollectedCoinCount = 0;
LevelDuration = 30.0f;
CurrentLevelIndex = 0;
MaxLevel = 3;
}
void ACH_GameState::StartLevel()
{
if (UGameInstance* GameInstance = GetGameInstance())
{
UCH_GameInstance* CH_GameInstance = Cast<UCH_GameInstance>(GameInstance);
if (CH_GameInstance)
{
CurrentLevelIndex = CH_GameInstance->CurrentLevelIndex;
}
}
SpawnedCoinCount = 0;
CollectedCoinCount = 0;
TArray<AActor*> FoundVolumes;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ASpawnVolume::StaticClass(), FoundVolumes);
const int32 ItemToSpawn = 40;
for (int32 i = 0; i < ItemToSpawn; i++)
{
if (FoundVolumes.Num() > 0)
{
ASpawnVolume* SpawnVolume = Cast<ASpawnVolume>(FoundVolumes[0]);
if (SpawnVolume)
{
AActor* SpawnedActor = SpawnVolume->SpawnRandomItem();
if (SpawnedActor && SpawnedActor->IsA(ACoinItem::StaticClass()))
{
SpawnedCoinCount++;
}
}
}
}
다음 레벨로 넘어가라는 메서드에 생성, 주운코인 카운트 출력로그를 넣었지만
UE_LOG(LogTemp, Warning, TEXT("Level %d Start!, Spawned %d coin"),
CurrentLevelIndex + 1,
SpawnedCoinCount);
로그에는 11(주운 코인 수)/0(스폰된 코인 수) 으로 나온다.
주운 코인 수는 제대로 카운트되고 있구나! + 스폰된 코인 수가 문제가 있구나! 를 알 수 있다.
초기화 되는게 여러번되나? 라는 생각에 각 초기화 되는 부분에 출력 로그를 넣었다.
//생성자 초기화
SpawnedCoinCount = 0;
UE_LOG(LogTemp, Warning, TEXT("SpawnedcoinCount=0"))
//레벨 시작시 초기화
SpawnedCoinCount = 0;
UE_LOG(LogTemp, Warning, TEXT("SpawnedcoinCount=1"))
하지만 각 로그들은 한번씩만 나오고 아이템을 주워도 나오지 않는다.
즉 초기화함수가 여러번 작동하는건 아니다!
스폰 코인 카운트에서 문제가 있나? 라는 생각에 카운트가 올라갈 때 마다 LOG를 호출하게 해봤다.
const int32 ItemToSpawn = 40;
for (int32 i = 0; i < ItemToSpawn; i++)
{
if (FoundVolumes.Num() > 0)
{
ASpawnVolume* SpawnVolume = Cast<ASpawnVolume>(FoundVolumes[0]);
if (SpawnVolume)
{
AActor* SpawnedActor = SpawnVolume->SpawnRandomItem();
if (SpawnedActor && SpawnedActor->IsA(ACoinItem::StaticClass()))
{
SpawnedCoinCount++;
UE_LOG(LogTemp, Warning, TEXT("SpawnedcoinCount / %d"), SpawnedCoinCount)
}
}
}
}
작동이 안된다. 여기 위 아래로는 로그 출력이 됐었기 때문에
if 조건문중에 하나가 문제가 있어 출력이 안됐다는 것을 알 수 있다
if문을 한번 체크해보기 위해 하나씩 해보기
UE_LOG(LogTemp, Warning, TEXT("FoundVolumes: %d"), FoundVolumes.Num());
이걸 FoundVolume밑에 넣었더니 문제가 없다.
if (SpawnVolume)
{
UE_LOG(LogTemp, Warning, TEXT("SpawnVolume found"));
}
else
{
UE_LOG(LogTemp, Warning, TEXT("SpawnVolume is nullptr"));
}
이것도 SpawnVolume을 설정한 if문 안에 넣었더니 잘 된다.
그렇다면
AActor* SpawnedActor = SpawnVolume->SpawnRandomItem();
if (SpawnedActor && SpawnedActor->IsA(ACoinItem::StaticClass()))
{
}
이녀석이 문제라는 것을 알 수 있다.
나는 그래서 SpawnRandomItem함수를 찾아가봤다.
AActor* ASpawnVolume::SpawnRandomItem()
{
if (FItemSpawnRow* SelectedRow = GetRandomItem())
{
if (UClass* ActualClass = SelectedRow->ItemClass.Get())
{
SpawnItem(ActualClass);
}
}
return nullptr;
}
보호막들을 쳐놨는데 막상 SpawnItem(ActualClass);를 반환을 안했다.
반환을 했더니. 아주 잘된다.
느낀점
나는 그냥 뭐가 문제인지 모르겠는데 답답하고 짜증이 났지만. 그래서는 스트레스가 계속 쌓이고 점점 우울해진다. 이런거 하나하나에 성취감을 느껴야 한다. 안된다는것을 알게되는것도 중요하다.
내가 하는 시도로 소거법으로 하나씩 지우면서 제대로 된 상황을 점점 구체적으로 이해하고있다는거를 알아야한다.
내가 하는것은 시험이 아니라 실험이다. 연속성이 있고, 왜 안되는지를 알게된다면 그건 성공한 실험이다. 오류가 해결되지 않았다고 전진하지 않은게 아니다.조건을 알아내는것도 성공이라고 생각하고 작은것에도 성취감을 느끼며 즐거움을 느끼며 즐겁게 코딩을 할 수 있는 개발자가 되고싶다.
'C++ > 개념정리' 카테고리의 다른 글
상태 패턴 (0) | 2025.03.05 |
---|---|
전략패턴 (0) | 2025.02.26 |
개념정리[연산자(&*)] (0) | 2025.02.07 |
C++[코드변경 깃허브 적용] (0) | 2025.01.13 |
C++[디자인 패턴] (1) | 2025.01.06 |