Pixel Streaming is crashing on emitUIInteraction() after using open level

Version: 4.21.2-4753647+++UE4+Release-4.21

Hello,

if have set up a scene for testing pixel streaming.

I have mapped two keys to change levels using an “Open Level” node.
So pressing button A opens level A. And pressing button B opens level B.
The setup works fine even inside pixel streaming.

However, i’m trying to practise some player page to ue4 communication now.

I am using emitUIInteraction(); to send strings to the engine, triggering a custom event bund to OnPixelStreamingInputEvent, to finally open a level.
This only works once. Subsequent calls are either ignored or crashes the engine altogether.

Since pixel streaming works fine as long as i do not use javascript input, i suspect the error is perhaps in apps.js. But i can not see it.

Any help is kindly appreciated. Thank you!

-Roman.

I am also having this exact same problem:

  1. Pixel-streaming starts in ‘LevelOne’.
  2. Trigger emitUIInteraction() in the browser.
  3. The custom event in LevelOne gets the message and calls ‘Open Level’ to switch levels to ‘LevelTwo’.
  4. Trigger emitUIInteraction() in the browser - with the intention of going back to LevelOne.
  5. Nothing happens. The custom event in LevelTwo does not get called.

So long as I don’t use ‘Open Level’ to change levels I can trigger emitUIInteraction() multiple times in the browser and the custom event is called successfully to stream levels.

Has anyone got pixel-streaming to work with more than one call to ‘Open Level’?

I solved the problem by modifying the code of PixelStreamingInputDevice.cpp this way. This answer also addresses the bug UE-69916.

From:

FString UIInteraction;
while (UIInteractions.Dequeue(UIInteraction))
{
	for (UPixelStreamingInputComponent* InputComponent : InputComponents)
	{
		InputComponent->OnPixelStreamingInputEvent.Broadcast(UIInteraction);
		UE_LOG(PixelStreamingInputDevice, Verbose, TEXT("UIInteraction = %s"), *UIInteraction);
	}
}

to:

FString UIInteraction;
while (UIInteractions.Dequeue(UIInteraction))
{
    auto LocalPlayer = GEngine->GameViewport->GetWorld()->GetFirstLocalPlayerFromController();
    auto Components = LocalPlayer->PlayerController->GetComponentsByClass(UPixelStreamingInputComponent::StaticClass());
    for (auto Component : Components)
    {
        UPixelStreamingInputComponent* InputComponent = (UPixelStreamingInputComponent*)Component;
        InputComponent->OnPixelStreamingInputEvent.Broadcast(UIInteraction);
        UE_LOG(PixelStreamingInputDevice, Verbose, TEXT("UIInteraction = %s"), *UIInteraction);
    }
}

The problem is in PixelStreamingPlugin.cpp: the OnGameModePostLogin creates a UPixelStreamingInputComponent just once inside of the method OnGameModePostLogin and adds it to the InputComponents array.
Substantially in the first level you bind the event to the only valid UPixelStreamingInputComponent (which is the same on which the events will be broadcasted). When you open another level you bind the event to a new UPixelStreamingInputComponent, which is not the one on which the UIInteraction events will be broadcasted (because it is not the one referenced in the InputComponents array).

With my changes the UPixelStreamingInputComponent is not taken from the InputComponents array (which is not updated) but is taken from the PlayerController, so it is always the valid one.

While waiting for an official fix you may use this solution.