Unreal

스폰될 Actor 의 위치에 미리 대기할때의 문제

느억맘 2024. 2. 13. 22:38

Actor 가 스폰될 지점에 캐릭터가 미리 가서 대기타고있으면 Trigger 가 발동되지 않는 문제가 발생한다.

원래대로라면 나머지 상자들도 사라져야하는데 사라지지 않음 -> Delegate 발동이 되지 않음.

 

void AABStageGimmick::SpawnRewardBoxes()
{
	for (auto& RewardBoxLocation : RewardBoxLocations)
	{
		FVector Location = GetActorLocation() + RewardBoxLocation.Value + FVector::UpVector * 30.f;
		AABItemBox* Box = GetWorld()->SpawnActor<AABItemBox>(RewardBoxClass, Location, FRotator::ZeroRotator);
		if (Box)
		{
			Box->Tags.Add(RewardBoxLocation.Key);
			Box->GetTrigger()->OnComponentBeginOverlap.AddDynamic(this, &AABStageGimmick::OnRewardTriggerBeginOverlap);
			Box->GetTrigger()->OnComponentHit.AddDynamic(this, &AABStageGimmick::OnRewardTriggerHit);
			//Box->GetTrigger()->oncomponent
			RewardBoxes.Add(Box);
		}
	}
}

그 이유는 동작 순서가 1. 생성 2. Collision 반응 시 삭제 인데, 미리 가있으면 생성만 하고 Collision 반응을 할 Delegate 호출까지 하지 않는 듯 하다.

 

해결방법

- Actor 의 충돌감지를 Overlap 이 아닌 Hit 으로 바꿈. (필요에 따라 Collision 의 Preset 추가를 해줘야 함), 그리고나서 SpawnCollisionHandlingOverride 를 이용해 아래와같이 소환지점에 캐릭터와 충돌하는지의 여부를 결정해 스폰.

 

void AABStageGimmick::SpawnRewardBoxes()
{
	for (auto& RewardBoxLocation : RewardBoxLocations)
	{
		FVector Location = GetActorLocation() + RewardBoxLocation.Value + FVector::UpVector * 30.f;
		FActorSpawnParameters Params;
		Params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
		AABItemBox* Box = GetWorld()->SpawnActor<AABItemBox>(RewardBoxClass, Location, FRotator::ZeroRotator, Params);

		if (Box)
		{
			Box->Tags.Add(RewardBoxLocation.Key);
			//Box->GetTrigger()->OnComponentBeginOverlap.AddDynamic(this, &AABStageGimmick::OnRewardTriggerBeginOverlap);
			Box->GetTrigger()->OnComponentHit.AddDynamic(this, &AABStageGimmick::OnRewardTriggerHit);
			RewardBoxes.Add(Box);
		}
	}
}

어거지로 스폰할경우 위와같이 생성됨. Overlap 을 사용했을 시 발생할 수 있는 버그같은 동작을 미연에 방지할 수 있어 더 좋은것 같다.

 

##수정

SpawnActor() 함수가 아닌 지연생성함수 SpawnActorDeffered() 를 사용하면 위의 문제를 원천적으로 차단할 수 있다는 것을 알게되어 위의 방법이 굳이 필요가 없어졌다.

 

void AABStageGimmick::SpawnRewardBoxes()
{
	for (auto& RewardBoxLocation : RewardBoxLocatoins)
	{
		FVector WorldSpawnLocation = GetActorLocation() + RewardBoxLocation.Value + FVector(0.f, 0.f, 30.f);
		FTransform Transform1(WorldSpawnLocation);
		AABItemBox* ItemActor = GetWorld()->SpawnActorDeferred<AABItemBox>(RewardBoxClass, Transform1);

		if (ItemActor)
		{
			//RewardBoxActor->Tags.Add(RewardBoxLocation.Key);
			ItemActor->GetTrigger()->OnComponentBeginOverlap.AddDynamic(this, &AABStageGimmick::OnRewardTriggerBeginOverlap);
			UE_LOG(LogTemp, Log, TEXT("DelegateAfter"));
			RewardBoxes.Add(ItemActor);
		}
	}

	for (const auto& RewardBox : RewardBoxes)
	{
		if (RewardBox.IsValid())
		{
			RewardBox.Get()->FinishSpawning(RewardBox.Get()->GetActorTransform());
		}
	}
}

일반적인 SpawnActor 일 경우 생성되자마자 ->Constructor, BeginPlay 등등으로 동시에 ItemBox 만의 Trigger 가 바로 설정되어 아래 기믹의 트리거가 설정되기도 전에 먼저 트리거가발동되어 예기치 않은 문제가 발생할 수 있음.

-> 기믹의 트리거가 먼저 설정되고 나서 아이템의 트리거가 설정되어야 하니, SpawnActorDeferred 가 필요한 것.

BeginPlay 즉, 아이템 트리거가 설정되기 이전에 기믹트리거가 설정됨으로써 안전하게 기믹트리거 작동

`

기믹트리거 설정이전에 BeginPlay 가 먼저 실행되버림,  아이템 트리거가 먼저 발동하게 되면서 예상치 못한 일이 발생가능

 

'Unreal' 카테고리의 다른 글

공부하면서 알게된 것들  (0) 2024.02.27
10강 게임데이터 관리  (0) 2024.02.14
기본 Actor 가 설정되는 방식  (0) 2024.02.13
Collision Resposes 에 따른 상관관계 정리  (1) 2024.02.05