How to detect when a texture is streaming in

Our game has a character select screen where we dynamically load in textures based on user customization, so that each time they select one of the characters, they see their personalized version of that character.

What I’m trying to do is not show the character while the textures are still streaming in. Instead, I want to hide the character and spawn in a particle effect until the textures are fully streamed, at which point the particle effect disperses and the character is made visible.

My issue currently is that I can’t find a reliable way to check that the texture is not finished streaming yet. The below code always seems to return that the textures are in “TexState_ReadyFor_Requests” even if they haven’t streamed in yet, and stepping through the debug code suggests that the requested and desired mips are the same.

Here’s the code I’ve been trying so far:

void AShooterActor::BeginSpawn()
{
	SetActorHiddenInGame(true);

#if PLATFORM_SUPPORTS_TEXTURE_STREAMING
    // Force the textures to begin streaming even though the actor is hidden
	PrestreamTextures(1, true);

	// Iterate over all components of that actor, get all the textures, and save references to them
	TInlineComponentArray<UMeshComponent*> Components;
	GetComponents(Components);

	for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++)
	{
		UMeshComponent* MeshComponent = Components[ComponentIndex];
		if (MeshComponent->IsRegistered())
		{
			TArray<UTexture*> OutTextures;
			MeshComponent->GetUsedTextures(OutTextures, EMaterialQualityLevel::Num);

			for (UTexture* Texture : OutTextures)
			{
				if (UTexture2D* Texture2D = Cast<UTexture2D>(Texture))
				{
					Textures.Add(Texture2D);
				}
			}
		}
	}

	// Make sure the textures haven't already finished streaming
	for (UTexture2D* Texture : Textures)
	{
		int StreamingStatus = Texture->PendingMipChangeRequestStatus.GetValue();
		if (!(StreamingStatus == TexState_ReadyFor_Requests || StreamingStatus == TexState_InProgress_Initialization) )
		{
			bIsStreamingTextures = true;
			USkeletalMeshComponent* Mesh = Cast<USkeletalMeshComponent>(GetComponentByClass(USkeletalMeshComponent::StaticClass()));
			SpawningParticleInstance = UGameplayStatics::SpawnEmitterAttached(SpawningParticle, Mesh);
			return;
		}
	}
#endif // PLATFORM_SUPPORTS_TEXTURE_STREAMING

	// If we get here, all textures are already loaded
	bIsStreamingTextures = false;
	SetActorHiddenInGame(false);
	OnTexturesFinishedStreaming();
}

Then in my Tick function, if the textures are still streaming in, I check through all the textures to determine if they’ve finished, at which point I make the actor visible:

void AShooterActor::Tick(float DeltaSeconds)
{
        Super::Tick(DeltaSeconds);

        if (bIsStreamingTextures)
	{
		bool IsStreamingComplete = true;
		for (UTexture2D* Texture : Textures)
		{
			if (Texture->PendingMipChangeRequestStatus.GetValue() != TexState_ReadyFor_Requests)
			{
				IsStreamingComplete = false;
				break;
			}
		}

		if (IsStreamingComplete)
		{
			if (IsValid(SpawningParticleInstance))
			{
				SpawningParticleInstance->DestroyComponent();
			}
			bIsStreamingTextures = false;
			Textures.Empty();
			SetActorHiddenInGame(false);
			OnTexturesFinishedStreaming();
		}
	}
}