Preloaded Resources

Overview

Preloaded resources are a good way to increase your initial page load performance by pre-processing the various resources that an HTML page needs in advance, for example by reading them from the hard drive and parsing or compiling them. This page mainly relates to the APIs or techniques specific to the Gameface Unreal Engine plugin and integration. It is highly recommended that you read the native Cohtml Preloaded Resources documentation for an extended overview and more engine-agnostic preloading techniques.

Preloaded Textures

Preloading texture resources is a fairly complicated process, which rightfully deserves its own page.

Preloaded HTML or CSS files

To preload an HTML or CSS file, you need to do the following:

  1. Obtain a pointer to the native cohtml::System. This can be done like this:
cohtml::System* NativeSystem = FCohtmlSystemHolder::GetSystem()->GetSystemPtr();

In some cases, you might need to create the system yourself.

  1. Call the respective API to load your file:
NativeSystem->PreloadAndCacheHTML(PathToFile); // or PreloadAndCacheCSS(PathToFile)

PathToFile can be any path that can be loaded through the FCohtmlFileHandler, similar to other paths you use in your UI - for example ones containing coui:// or other resource hosts.

  1. (optional) After the file is no longer in use, you can call the respective API to free the file from memory
// Clear a single file.
NativeSystem->RemoveHTMLCacheEntry(PathToFile) // or RemoveStylesheetCacheEntry(PathToFile)
// Clear the entire cache.
NativeSystem->ClearHTMLCache (PathToFile) // or ClearStylesheetCache(PathToFile)

The APIs used above are explained in detail in the native documentation

Preloaded Fonts

There are two main ways to improve your font performance in Gameface

Registering fonts early

You can register a font through the cohtml::System::RegisterFont API. This will allow Gameface to open a ISyncStreamReader and read the font description early on. If a font is not registered early on, Gameface will still do these operation during the initialization of your HTML page, with the following caveats:

  • Fonts are loaded asynchronously, which might mean that on the first few frames of loading the font it will still not be ready and your page will be displayed without a font.
  • The initialization of your page is an operation-dense point, so offloading any work to an earlier time is preferred.

Due to the above points, it is generally better to register all fonts before you use them. The Gameface integration automatically registers all ttf/ttc/otf fonts in the YourGame/Content/Fonts/ folder.

If you want to register a font yourself, you can do it like this:

  1. Obtain a pointer to the native cohtml::System.
cohtml::System* NativeSystem = FCohtmlSystemHolder::GetSystem()->GetSystemPtr();

In some cases, you might need to create the system yourself.

  1. Register your font
NativeSystem->RegisterFont(TCHAR_TO_UTF8(*PathToFont));

PathToFile can be any path that can be loaded through the FCohtmlFileHandler, similar to other paths you use in your UI - for example ones containing coui:// or other resource hosts.

For more information on the RegisterFont process under the hood, check out the native documentation.

Caching font data in memory

Generally speaking, fonts are loaded lazily in Gameface. Whenever a part of a font is needed, a corresponding ISyncStreamReader::Read() call is made (and the part is cached for the future). Gameface will also detect most glyphs you use in your UI in advance, and issue Read() calls as soon as the page starts loading. This provides a good general performance, but you can go a step further and cache the entire font in memory beforehand. This works for some use-cases where disk reads are too slow, or you wish to trade off as much memory for performance as possible.

Here is a rough outline of how to do it:

  1. Override the default FCohtmlFileHandler class with your own
  2. Make sure to pass your FCohtmlFileHandler override to the Gameface integration
ICohtmlPlugin::Get().OnGetFileHandler.BindLambda([=]()
{
	return MyFileHandlerOverride;
});
  1. Implement your own override of the OnResourceStreamRequest method, which returns your own ISyncStreamReader
// This is a shortened example, it is recommended to check out the full FCohtmlFileHandler::OnResourceStreamRequest implementation.
FCohtmlFileHandler::OnResourceStreamRequest(Request, Response)
{
    auto MyStreamOverride = new FMyStreamReaderOverride(Request->GetAbsoluteURL());
    Response->SetStreamReader(MyStreamOverride);
    Response->Finish(cohtml::IAsyncResourceStreamResponse::Success);
}
  1. Implement your own Read() semantics in your ISyncStreamReader object
FMyStreamReaderOverride::Read()
{
    // read from your preloaded buffer of data
}

Preloaded JavaScript

Preloading JavaScript resources is a fairly complicated process, which rightfully deserves its own page.

Creating the system early

In some cases, you might want to preload files at some very early point in your game, for example during the initial loading screen. Since the existence of a system is usually a prerequisite for file preloading, you might need to create the system yourself in those cases. The creation itself is easy and can be done like this:

FCohtmlSystemHolder::CreateSystem() // instead of FCohtmlSystemHolder::GetSystem()

Keep in mind that most Gameface managers are instantiated at this point, for example the FCohtmlTextTransformationManager or FCohtmlLocalizationManager. If you have any delegates which override them, such as ICohtmlPlugin::OnGetTextTransformationManager, make sure that they are bound before you call CreateSystem(). It’s recommended to go over the CreateSystem() method yourself and check if any of the delegates/settings you use to communicate with the Gameface plugin might be affected by the early creation of the System.