1.14.0.5
Coherent HB for UE4
A modern user interface library for games
FAQ

Can I load files over HTTP(S)?

Absolutely! The plugin uses UE4's HTTP module to download files whenever Hummingbird detects file requests over HTTP(S). You can download everything from the web (e.g. by setting the root URL of the page to use HTTP) or you can download just some files like images or data (e.g. via AJAX).

Check the example level */Maps/HTTPMap* in the HummingbirdFPS game that comes with the plugin for a demo.

Can I use a gamepad to control my UI?

Certainly! Hummingbird uses UE4's gamepad data to expose the HTML5 Gamepad API. You don't have to do anything on the game's side to enable the gamepad input, simply connect your controller, focus a Hummingbird View or UMG widget and you're good to go. See the ExampleMap for a sample that utilizes this functionality.

There are many ways one can bind gamepad buttons and axes. Hummingbird uses the standard gamepad mapping as described by the W3C here.

Warning
The HTML5 gamepad API uses polling instead of events (which the keyboard and mouse use). Due to this, it is mandatory that the state of all gamepads is updated on all views - even those that are not focused. If you have multiple conflicting views reading the gamepad state at the same time, you'll need to use JavaScript to control which view should listen for gamepad inputs.

How to seamlessly travel between levels with Hummingbird enabled?

You need to make a few changes to your code to use seamless traveling with Hummingbird.

  1. All the Hummingbird components that you'd like to preserve to the next level must have their parent actors added to the list of traveling actors.
  2. The unique instance of Hummingbird's AHummingbirdSystem must also be added to the same list.

The above steps can be achieved by overriding APlayerController::GetSeamlessTravelActorList in your player controller implementation using the following code (assuming that all objects containing Hummingbird components are tagged with "PreserveHummingbird"):

void AMyPlayerController::GetSeamlessTravelActorList(bool bToEntry, TArray<AActor*>& ActorList)
{
    // Add the actors containing Hummingbird components
    for (TActorIterator<AActor> It(GetWorld()); It; ++It)
    {
        if (It->Tags.Contains("PreserveHummingbird"))
        {
            ActorList.Add(*It);
            break;
        }
    }
    // Add the unique instance of AHummingbirdSystem
    for (TActorIterator<AHummingbirdSystem> It(GetWorld()); It; ++It)
    {
        ActorList.Add(*It);
        break;
    }
}

Finally, make sure that no AHummingbirdSystem actor exists in the target level. If this is not the case, the old system and the new one will clash and your views will experience weird behavior (such as time passing by faster than it should).

What happens with the gamepad when the focus returns from the UI back to the game?

The system will set all buttons and axes to zero by default. This prevents the case in which a pressed button will continue to be pressed in the UI while the focus is still in the game. However, you can change the gamepad behavior by calling AHummingbirdInputActor::GetGamepadBehaviourDelegate() which will return a delegate you can bind your callback to. For example

auto MyFunc = [](uint32 UserIf) -> EGamepadFocusLostBehaviour
{
    return EHBGamepadBehaviourOnFocusLost::HBResetState;
}   InputActor->AHummingbirdInputActor::GetGamepadBehaviourDelegate().BindLambda(MyFunc);

Your function has to return one of these values:

EHBGamepadBehaviourOnFocusLost::HBResetState - Set the current state to zero. This is default behavior. EHBGamepadBehaviourOnFocusLost::HBUseCurrentState - Will keep the last known state. Note that this will trigger the behavior mentioned above. EHBGamepadBehaviourOnFocusLost::HBUseStateBeforeReset - Will save the last known state, set the current state to zero and once focus is regained by UI that saved state will be reapplied

Note
You cannot bind your function to the delegate from Blueprints, you must use C++.

How do I localize my game?

  1. Follow UE4's localization tutorial to setup the required translations.
  2. Inside the UE4 editor, go to Hummingbird -> Options and check Enable Localization.
  3. For any element you need localized add the data-l10n-id attribute and pass the namespace and key of the translated FText e.g.:
    <button data-l10n-id='MyNamespace.MyTextKey'></button>
    

See the Localization Tutorial for a detailed walkthrough.

Building a UE4 dedicated server

To build a dedicated server for your game, you have to setup a Server Target. You can check the HummingbirdFPSServer.Target.cs file located in our HummingbirdFPS sample game HummingbirdFPS/Source/HummingbirdFPSServer.Target.cs

You can check the whole procedure of Cooking the data for your server and building it here: https://wiki.unrealengine.com/Standalone_Dedicated_Server

Our UI uses a lot of fonts, can I tell to Hummingbird to load them all, without using `@font-face`?

Yes, any font placed in */Game/Content/Fonts* will be automatically loaded when the game starts. Please note that Hummingbird requires the raw .ttf and .otf files (not the .uasset files that UE4 will generate for them). This means that in order to get your fonts packaged, you'd have to add the Fonts directory under Edit -> Project Settings -> Packaging -> Additional directories to always package.

Any font loaded this way will be available immediately after the game starts to be used as a font-family.

My game doesn't cover the entire screen but I'd like my HUD to do so. How do I do that?

If you are using letterboxing or your game is running on a platform with a constrained safe zone you HUD will be scaled appropriately. However, you might desire the HUD go over game's boundaries and this is possible by unchecking the Respect Safe Zone and Respect Letterboxing settings found under Hummingbird -> Options in the UE4 editor. This will cause the HUD to disregard the boundaries. To understand how these properties interact with each other see the following graphic:

safezone_letterboxing_interactions.png
Safe zone & Letterboxing

By default Hummingbird will respect both the safe area and letterboxing boundaries.

How do I keep the UI running while the game is paused?

Simply go to Hummingbird -> Options and check Tick While Game Is Paused

A part of my UI seems to be a couple frames behind the game. What is happening and how do I fix it?

This might happen if something in your UI depends on actor/world updates and must be perfectly in sync to look right. The reason this happens is because our component ticks during TG_StartPhysics and any bindings are sent during TG_DuringPhysics, but cameras are updated between TG_PostPhysics and TG_PostUpdateWork. We've added an option to delay the component's ticks to TG_PostUpdateWork and after any bindings are sent, which makes it so the UI receives the updated bindings before drawing. To enable the option, either enable it from the Editor (click on your Hummingbird component and tick Delayed Update) or enable it using SetupHBView (the bDelayedUpdate argument - false by default). Alternatively, you can use EnableDelayedUpdate(true) on the component - available in both blueprints and C++.

Note
This option should only be used if absolutely necessary - when a visual effect in the UI has to be perfectly in sync with something in the game world (i.e. nameplates above actors). It could have a negative impact on performance depending on the circumstances, so use with care.
Warning
This option does not work on data sent via blueprints. To enable the effect for BP code, you must add a Set Tick Group node to the BeginPlay event in the blueprint with self as the target and Post Update Work as the tick group (in addition to enabling the option). This is needed, because blueprints tick during StartPhysics by default, which is before the cameras are updated and you will be sending old data (from the previous tick).

How to automatically use GPU-compressed images instead of other formats?

Imagine that you have the following case:

<img src="foo.png"></img>

Then, in order to save memory and decoding time, you may want Hummingbird to automatically load a matching DDS file if one exists.

Hummingbird doesn't support automatic fallback to DDS images when they are available but you can achieve it by slightly modifying the plugin following two steps:

  1. For each PNG file add DDS variant with the suffix *_compressed*. For example, if you have image "foo.png" you need to add "foo_compressed.dds" one in the same folder.
  2. Replace the void FHummingbirdFileHandler::ReadResource function's body in the HummingbirdFileHandler.cpp with the following code:
if (TryUsePreloadedResource(ResourcePathNonConst, Response))
{
return;
}
FString ResourcePathNonConst = ResourcePath;
if (ResourcePathNonConst.Contains(TEXT(".png")))
{
FString ResourcePathDds = ResourcePathNonConst.Replace(TEXT(".png"), TEXT("_compressed.dds"));
auto& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
if (PlatformFile.FileExists(*ResourcePathDds))
ResourcePathNonConst = ResourcePathDds;
}
int64 Start = 0;
int64 End = 0;
bool bIsRangeRequest = IsRangeRequest(Start, End, Request);
TArray<uint8> Buffer;
int64 FileSize = 0;
if (!TryReadFile(ResourcePathNonConst, Start, End, bIsRangeRequest, Buffer, FileSize))
{
UE_LOG(LogHummingbird, Error, TEXT("Could not read file '%s'."), *ResourcePathNonConst);
Response->Finish(cohtml::IAsyncResourceResponse::Failure);
return;
}
SetResponseHeaders(FileSize, Buffer.Num(), Start, bIsRangeRequest, Response);
FMemory::Memcpy(Response->GetSpace(Buffer.Num()), (const char*)Buffer.GetData(), Buffer.Num());
Response->Finish(cohtml::IAsyncResourceResponse::Success);

Saving Debug Render Frames

You can use DebugSaveNextFrame and BeginDebugFrameSave methods on Hummingbird components/UMG widget which will capture rendering frames and save them to files in GameDir/Saved/Hummingbird/ folder. This can be useful when debugging rendering related issues.

As of now, these files can only be inspected by our own internal tools and you can't inspect them yourself. However, in the case of a graphics artifact, you can send them to our support team for investigation.

Note this is only for debugging and it has performance implications when used.

  • DebugSaveNextFrame forces a redraw on the whole UI.
  • BeginDebugFrameSave Starts saving every frame without forcing redraw and actually saving only the changed parts of the UI.

Part of my UI seems blurry when moving. What's causing this?

This is caused by the anti-aliasing algorithm used by the engine. When Temporal AA is used (Unreal's default choice) in-game UI will be blurry.

How to fix it: Change AA algorithm to FXAA or disable AA.

If Temporal AA is needed:

  1. Open HBMaterial from Hummingbird Plugin contents.
  2. Check Responsive AA property in Translucency tab in the Details of the material.
Note
If the in-game surface is transparent the objects behind the surface will be aliased. Unfortunately, this is an issue with the way UE4 handles in-game UI.