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:
- 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.
- 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.
- (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:
- 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.
- 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:
- Override the default
FCohtmlFileHandler
class with your own - Make sure to pass your
FCohtmlFileHandler
override to the Gameface integration
ICohtmlPlugin::Get().OnGetFileHandler.BindLambda([=]()
{
return MyFileHandlerOverride;
});
- Implement your own override of the
OnResourceStreamRequest
method, which returns your ownISyncStreamReader
// 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);
}
- Implement your own
Read()
semantics in yourISyncStreamReader
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
.