인프런 커뮤니티 질문&답변

k ch님의 프로필 이미지
k ch

작성한 질문수

이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해

9강 무한맵의 제작

블루프린트(에디터)에서 지정한 ComboActionData가 null이 되는이유

작성

·

327

·

수정됨

0

안녕하세요

AI시스템 구현도중 ComboActionData를 불러올수 없는 문제가 생겨서 질문 드립니다.

우선 이것저것 바꿔서 실습 해보는 중이라 강의 코드랑 다른부분이 있을순 있습니다만 베이스는 강의코드입니다...

void ATLStageGimmick::OnOpponentSpawn()
{
	const FTransform SpawnTransform(GetActorLocation() + FVector::UpVector * 88.0f);
	
	ATLCharacterNonPlayer* OpponentCharacter = GetWorld()->SpawnActorDeferred<ATLCharacterNonPlayer>(OpponentClass, SpawnTransform);
	if (OpponentCharacter)
	{
		OpponentCharacter->OnDestroyed.AddDynamic(this, &ATLStageGimmick::OnOpponentDestroyed);
		OpponentCharacter->SetLevel(CurrentStageNum);
		OpponentCharacter->FinishSpawning(SpawnTransform);
	}
}

우선 기믹 코드쪽에서 이렇게 스폰을 해주는데요,

(예제랑 같습니다)

 

CharacterNonPlayer를 상속받아 BP_EliteBoss라는 이름으로 블루프린트를 만든뒤 기믹 엑터에 이렇게 설정을 해줬습니다. 그리고

 

BP_EliteBoss안에 필요한 몽타주와 ComboActionData를 설정해줬는데요

 

그래서 게임을 실행해보면 정상적으로 스폰도 되고 이동도 합니다. 그런데 정작 공격을 진행하면 ComboActionData가 없다는것 아니겠습니까..? 저는 분명 블루프린트에서 ComboActionData를 넣었는데 말이죠..

 

혹시 SpawnActorDeferred하게되면 에디터에서 지정한 에셋들은 사용할 수 없는건가요??? 해결방법을 찾다 안돼서 질문 드립니다...

 

답변 2

0

이득우님의 프로필 이미지
이득우
지식공유자

제 예제에서 ComboActionData는 생성자에서 설정하기 때문에 에디터가 시작되기 전에 null이 아니어야 합니다. 생성자 코드에서 브레이크포인트 걸어보시고, 이 때 널인지 한번 체크해보시겠어요?
만약에 생성자에서 널이 아니면, 이후 다른 로직에 의해서 지워진다는 건데 이 부분은 직접 확인하는 수 밖에요.

k ch님의 프로필 이미지
k ch
질문자

아아 그러네요 강의내용엔 ConstructorHelper를 이용해 직접 가져 왔네요,

제가 강의를 들으면서 조금 의아 했던게 저렇게 직접 에셋을 가져오는 것이 좀 아쉽다 라는 생각을 했었습니다.

 

그래서 블루프린트에서 지정할수 있도록 하면 더편하지 않을까? 생각 헤서 이렇게 바꿧는데 결과적으론 안되는거 같네요.. 유니티처럼 직접 끌어다 가져오는게 안되는건가 .. 조금더 공부를 해봐야 알거같아요

 

우선 ComboActionData가 null이되는 정확한 원인은 찾지 못했습니다. null로 세팅해주는부분도 없고 아예 생성될때부터 없는거같은데요..

제가 생각해봤을때 객체를 new해서 만들때 리소스가 같이 할당 되어있다는거 자체가 말이 안되는거 같기도 합니다.

 

그래서 방법을 바꾸어야 될거같은데요 .

 

제가구현 하려고 하는 목표는 에셋들을 유동적으로 바꿀수 있도록 하는것입니다.

 

나중에 NPC캐릭터가 많아지고 사용하는 몽타주와 데이터 에셋이 달라질거같아 EditAnyWhere로 블루 프린트에서 직접할당해주려 저렇게 만들었는데요

 

사용할 에셋과 몽타주 등등 미리 설정해두고 불러올수 있는 방법이 있을까요?

 

Config파일에서 에셋의 경로를 이용해 FStreamableHandle으로 리소스 로딩했던 것 처럼 구현을 하여야 할까요?

 

크리스마스에 친절한 답변해주셔서 정말 감사합니다 ㅜㅜ

이득우님의 프로필 이미지
이득우
지식공유자

음.. 블루프린트로 로딩하는 것은 당연히 됩니다. 다만 액터를 스폰할 때, 블루프린트 클래스를 지정해줘야 할텐데요, OpponentClass 타입 정보를 어떻게 선언하셨는지요?

C++클래스를 상속받은 블루프린트 클래스를 만들고 TSubclassof<>를 사용해 스폰할 타입 정보를 에디터에서 설정하도록 하거나, C++에서 진행한다면 LoadClass함수의 인자에 블루프린트 경로에 _C를 붙여서 블루프린트 타입을 불러와야 할 것으로 보여집니다.

k ch님의 프로필 이미지
k ch
질문자

image이렇게 선언 했습니다... 에디터에서 새로만든 블루프린트를 끌어도 넣었구요..

 

 

// Fight Section
OpponentSpawnTime = 2.0f;
OpponentClass = AABCharacterNonPlayer::StaticClass();

지금 찾아보니 기믹엑터의 생성자코드에 이렇게 StaticClass를 가져와 세팅을 해주고 있었네요....

이렇게 되면 아무리 에디터에서 에셋을 가져와 넣어줘도 ComboActionData가 없지 않을까요??

구글에 찾아보니 StaticClass는 컴파일타임에서 생성된 UClass정보 라고하네요.

만약 맞다면 어떻게 스폰 시키는게 맞을까요.. 블루프린트 에디터에서 설정한 객체를 스폰하고싶습니다.

이득우님의 프로필 이미지
이득우
지식공유자

음 사실 앞으로 블루프린트 클래스를 활용할 예정이라면, 기믹도 블루프린트로 제작해서 처리하는게 좋긴 합니다. C++ 기믹을 상속받은 블루프린트 기믹의 기본 값에서 OpponentClass를 블루프린트 클래스로 지정하면 원하는대로 동작할 겁니다.
만일 C++로 다 해결하고 싶다면 결국 C++에서 블루프린트 클래스를 읽어들여야 하는데, 왠지 거꾸로 사용하는 느낌이지만, 아무튼 생성자에서 블루프린트 클래스를 얻어오려면 다음과 같이 사용해주면 됩니다. 주소는 애셋을 우클릭해 레퍼런스를 복사해오고 주소 마지막에는 꼭 _C를 붙여주어야 합니다.

static ConstructorHelpers::FClassFinder<APawn> DefaultPawnClassRef(TEXT("/Script/Engine.Blueprint'/Game/ArenaBattle/Blueprint/BP_ABCharacterPlayer.BP_ABCharacterPlayer_C'"));
if (DefaultPawnClassRef.Class)
{
	DefaultPawnClass = DefaultPawnClassRef.Class;
}

 

0

안녕하세요, 인프런 AI 인턴입니다.

강의를 듣는 도중 발생한 ComboActionDatanull이 되는 문제에 대해 질문해주셨군요. 이와 유사한 문제를 다룬 기존의 질문&답변 내용을 참고하실 수 있는 링크를 제공해 드리겠습니다. 해당 답변에서는 FString::Printf 사용 시 발생한 문제에 대한 해결 방법을 제시하고 있으니, 비슷한 문제의 해결책을 찾는 데 도움이 될 수 있을 것 같습니다.

  • 강의 제목: 이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
  • 질문 제목: 안녕하세요. 질문하나 드리겠습니다.

안녕하세요. 질문하나 드리겠습니다.

이 내용이 해결책이 되시길 바라며, 충분한 해결이 되지 않을 경우 추가 질문을 남겨주시면 감사하겠습니다.

k ch님의 프로필 이미지
k ch

작성한 질문수

질문하기