FREE: Web UI (HTML/CSS/JS Interface)

Thank you for the great plugin and your efforts. I have followed the setup instructions and created my widget on UE 4.25. I seem to have a problem about Focus. The default BP setup shown in HUD is not focusing after creation. Player needs to click on the widget to gain focus. But adding a delay(min 0.3s) after last node which is Load File and calling helper function Focus on Browser(variable returned from GetBrowser) after the delay seems to fix this. Calling Focus function just after Load File also doesn’t seem to work. This might be related to load times and instances not being available at the time. Can we double check this if this is a bug or if this is just an error on my side. Thank you.

What you’re discovering is the disconnect between the game instance and the browser instance and there is already a mechanism in the example project that handles all of this for you that you might be overlooking.

Basically there’s no reason to be calling Focus() immediately after the LoadFile() function. In fact if the browser widget hasn’t even created the internal viewport widget yet, there is no way for the Focus() function to find it, so it won’t even work anyway if you call it prematurely before the widget has fully initialized. Instead let’s go over a typical setup which is demonstrated for you in the example project…

You first create the browser widget, add it to the viewport (set it to hidden) and load your initial file. During this time you could be displaying a loading image or a loading widget while the browser widget is hidden. At this point you’ve handed off control to the browser instance, so the game instance should be waiting for some kind of confirmation from the browser instance that the page was successfully loaded before making the widget visible.

So what you do is register a jQuery.ready() event in your HTML page that will send an event to the game instance once the page is ready. In terms of JavaScript this means the $.ready() function calls ue4(“ready”) which then changes the browser widget visibility from hidden to visible (and could hide your loading image/widget).

It is here in the UE4 ready event (the moment you make it visible) that you want to set focus to the browser widget. This guarantees the internal viewport widget has already been created, and that your page actually loaded correctly before handing off focus. Otherwise if your ready event is not called after a certain amount of time, you can assume the browser did not load correctly and handle your error (such as sending a report using the HTTP blueprint plugin or displaying an error widget).

So long story short, create a boolean variable in your blueprint called “ready” and setup a 5-10 second delay node after you call the LoadFile() function (and initially hide the browser widget). If the boolean is still false after the delay, then handle your “interface failed to load” error situation. Now create a “ready” case in the switch of your broadcast event and have it set the boolean variable to true, make the widget visible, and then focus the browser widget (don’t forget to register a jQuery ready event that will broadcast your UE4 ready event).

The plugin has been updated for 4.26 and now includes IME support for different languages. Thanks to “iletai” and “dtcong510” on GitHub for reporting this issue.

The plugin has been updated again and now includes a custom scheme handler. There is also a new corresponding “Load” function that will serve as the primary means of loading game interfaces from this point forward. The example project in the releases download on GitHub has been updated as well. You can learn more by reading the updated load section of the documentation.

Prior to this update there were two primary ways of loading files or content. Either the LoadFile() function which uses [FONT=Courier New]file:/// internally or LoadContent() which could access data in [FONT=Courier New].pak files but was just a glorified wrapper for LoadHTML(). This presented a problem where you could choose to package either [FONT=Courier New].html and sometimes [FONT=Courier New].js files into your [FONT=Courier New].pak files, but then this HTML was loaded using LoadHTML() and the [FONT=Courier New]http:// scheme. The browser would have no way to access any scripts, stylesheets, or images that go with the HTML since it was loaded as raw text. However you could instead use LoadFile() which used [FONT=Courier New]file:/// internally and then the browser could access any local files that go with the HTML. But this presented the problem of now requiring this content to be directly on the disk and no longer packaged away inside the [FONT=Courier New].pak files of your shipping build.

So you essentially had to choose between having your interface packaged away with all the other content as a single file or exposed as raw files directly on disk in order to access images.

Now you no longer have to choose between these two options because a custom scheme handler has been implemented. Just use the new Load() function to access a file inside the /Content directory and it will be loaded in the browser via a custom [FONT=Courier New]pak:// scheme instead of [FONT=Courier New]http:// as LoadHTML() does. That means all local references to scripts, stylesheets, and images (such as [FONT=Courier New]<img src=“ue4.png” /> references) will just work as they would on a normal website.

So now all content can be served up through the Unreal Engine file system using this custom [FONT=Courier New]pak:// scheme. And that means you can choose to use either the “Additional Non-Asset Directories to Package” or “Additional Non-Asset Directories To Copy” options in your project settings. It doesn’t matter if the content is directly on disk in the /Content directory or packaged inside [FONT=Courier New].pak files in shipping builds, it will just figure everything out the same way the engine does for standard .[FONT=Courier New]uasset files.

Great Updates!

So I’ve successfully packaged sample project with latest UE4.26 however, after trying to launch the .EXE, nothing ever pops up. :frowning:


Sorry for the late reply, I was sick and haven’t been around much lately. It’s unfortunate that you’re having trouble with the plugin but I will try to see what I can do. The thing is this code snippet that accesses the data from PAK files is the same as it was for the LoadContent() function. So if the custom [FONT=Courier New]pak:// scheme handler isn’t working for you, then that means the LoadContent() function wouldn’t have been working either.

I will try and make a production/shipping build of the example project when I have some time and let you know if I run into the same issue. For now you might want to try the LoadContent() function to see if that works, which could at least provide us some insight if data is being read from your PAK files.

Lastly did you make sure to include your custom folder/directory in your project settings? That is like the most common mistake that people make, where everything is setup correctly but they forget to set the “DirectoriesToAlwaysStageAsUFS” setting in their config. This is outlined in the documentation on pages 18 and 20.

I also forgot to mention yesterday that we’ve noticed recently a lot more people reaching out that cannot really communicate effectively. They’re most likely using Google Translate or something to send their questions. After looking into the web traffic history of the documentation and GitHub insights it seems there is a lot more traffic recently coming from China. So we’re looking for someone that speaks fluent English and Chinese that would be interested in helping answer questions on GitHub. If you speak both languages and are interested in helping out with this free plugin it would be greatly appreciated.

The issue with packaged projects not launching in 4.26 has been fixed. If you’re planning to compile the plugin yourself you can find the code changes here:

Otherwise new builds of the plugin will be uploaded to GitHub most likely around the time 4.26.2 is released. And probably for some older engine versions as well.

Thank you for your hard work :wink: . now It works pretty good on shipping build.

BUT still broken when Play In Editor like below screenshot attached (the script not work I think )


Um, no. The example project works just fine, I literally went back to my work machine after I had just closed everything up and tested it right now after you said it doesn’t work. So thank you for wasting my time. Maybe you should double check things before just blatantly reporting that something doesn’t work. You know how many times I find things that I think are broken, and then want to go report it?

But to prevent myself from looking like an idiot, I’ll actually take the time to try out the issue on a separate operating system or something more than just “oh dear it didn’t work this one time on my one machine, so it must be broken” but again, if somebody did that, it would just make them look like an idiot. cough cough

So coming here a few months ago to report your shipping build crashing without actually providing any steps to reproduce the problem or any kind of a crash report or just something at all that would be helpful towards looking into the problem IS NOT HELPFUL (quick shout out to the guy on GitHub who actually provided a crash report and actually helped address the problem). And since it seems that you are now just reporting anything that you feel isn’t working on your computer as if we’re your personal Geek Squad…well now I’ve learned not to waste my time looking into anything you report anymore.

What an amazing plugin! Thanks for this!

Everything works just fine, except the frame rate is quite low. Animations and scrolling feels laggy. Tested this plugin with, and it never exceeds 35 fps, meanwhile the game is running at 300+ frames per second without VSync. I’ve tried to change FPS setting of that widget, but anything above 30 fps does not work. Then I tried to use Unreal Engine “Web Browser” plugin, and it too renders at 30 fps. So, it looks like it’s Unreal Engine CEF problem? Is it just me having this issue? Are there any solutions?

I am using Unreal Engine 4.26.1, testing on a empty project.

Glad you’re finding the plugin useful, and thank you for specifying that you’re testing on an empty project. The UE4 CEF can be used with WebGL disabled (default in 4.23) or enabled (default in 4.24) which comes at a significant cost of performance. You’ll get something much more responsive and a lot closer to 60 FPS if you use a browser widget with WebGL disabled.

There is unfortunately no way to change this setting without compiling the engine from source yourself. The documentation explains exactly what to do. Otherwise if you must use the default engine installations via the Epic Launcher then your only other option is to revert back to 4.23 which quite honestly I highly recommend anyway. There were some major overhauls to the engine in 4.24 and 4.25 and many things are still broken, even in 4.26 which most likely won’t get fixed any time soon, if ever. So I would strongly advise using 4.23 or you’re going to start finding a lot of little issues here and there and wish you wouldn’t have gone so far forward.

Now the fact that you’re getting 300+ FPS in the engine is irrelevant, this is an external subprocess that is sending texture updates to your GPU from your CPU. The UnrealCEFSubprocess.exe runs at its own desired frame rate, which maxes out at 60 FPS anyway when using an external rendering process. The only way to have a web-based interface that runs at the same FPS as your game (meaning it is integrated into the engine and runs on every tick) is to use something such as WebKit instead.

We’ve planned to integrate WebKit for many years now but have just not found the time to take on that project just yet. However it is the only way to get these web-based interfaces working on consoles (although there might be a PS4 workaround) so we are still planning to do that sometime in the future.

Love this Plugin :slight_smile:

Somehow IME doesn’t work for me on 4.26 even using native WebBroswer widget, but I made it work before on 4.24 with custom code below, and added options to show Contorls and AddressBar, Can you intergrade these codes into this plugin? that would be perfect :wink:


Well if you can read C++ then you must have missed this…

But alright, I’ll add a section to the documentation in the next update about how to enable IME support (cause you assumed everyone in the world uses IME and wants it enabled by default).

Thank you sooo much :wink:

I’m not familiar with C++ just grabed code from somewhere, and here is my wishlist:

  1. if you can add options to show Contorls and AddressBar that would be grateful :wink:

  2. I see upload file to web page works but how to download file from page? if I have a button on page to download the file.

  3. Would you add these features for 4.24 such as load from .pak file or if it’s only for 4.26 ?

  4. any consider to add Tab based featrue? like this…ser-plugin-umg


Hey guys just a quick update on a useful new feature…but I can’t start without mentioning this awful new forum interface. Not only is it extremely unreadable with the overbolded text but the overall layout and spacing of everything is just ridiculous. Would you expect anything less from Epic Games though? This is like the perfect metaphor for how they treat their engine updates…half-arssed and unfinished.


Plus I can’t even edit the first post anymore which means making updates to this thread isn’t really going to be possible any time soon. So since the forums are pretty much bricked what we might do is finally build out our website. Right now there was nothing but some placeholder pages and a link to the documentation, but we could get it all updated with actual images and descriptions of the plugins. Most importantly we would include an option to sign up for an email list so you can get updates about our plugins without having to visit these awful forums anymore. I’ll be sure to let you all know when I’ve taken some time to get that setup, but I definitely think that’s what we’re going to do.


Anyway moving on to the update. We’ve been trying to migrate from using UE4-based INI files to our own custom JSON files. This not only provides more flexibility but also allows you to lock down your INI files so end-users cannot edit those settings (such as rendering or scalability settings to cheat and hide foliage). It creates a great separation between engine settings you don’t want them to touch and your own custom game settings.

What I mean is, you usually have Engine.ini and Game.ini and Input.ini and GameUserSettings.ini and so on all in your AppData folder. But you shouldn’t have any of these in there except for GameUserSettings.ini and maybe Input.ini but as usual these engine developers don’t care at all about security. So buried away deep in the C++ code (without any access from project settings) is a way to disable all INI files except the GameUserSettings.ini which forces these INI files to ONLY be in the PAK files of your shipping builds.

Here’s the problem though. If you do this and start using JSON files as a new file type for your custom settings files, they quickly become unusable due to the JSON standard. It does not support trailing commas and even worse it does not support line or block comments:


Since this is all considered invalid JSON, if you accidently include a trailing comma, your JSON will not parse. If you accidently include a comment somewhere, your JSON will not parse.

So there’s a significant difference between wanting to parse valid JSON for HTTP which should remain strict, and user-edited JSON that could easily become “invalid” even though their text editor had no problem with them adding the comments or a trailing comma.

Therefore the following function has been developed for this very purpose:


Now when initially trying to tackle this problem I came across a few examples on Stack Overflow. No joke, some dude tried to solve it with RegEx, was all like “yea I made sure to cover all the potential options” and had an entire explanation about how RegEx will do greedy capturing, ect. In fact this was the “accepted solution” and had over 100 upvotes on it. Can you believe so many programmers are this stupid? Literally the only way to properly parse/capture comments is with TOKENIZATION! That example from Stack Overflow? It can literally be broken in 2 seconds by using an escape character in your strings:

{ "this is a key": "this is a string with \"quotes\" in it" }

And it would have absolutely no idea what to do because RegEx is OBVIOUSLY not the right tool for the job at all. So why bring this up? Because we actually took the time to implement the RIGHT SOLUTION which properly TOKENIZES and knows the context of whether a character is escaped, inside a comment, or inside a string. So you don’t have to worry about “accepted solution” Stack Overflow morons putting inferior code into your games that will ultimately just break the moment someone tries to type a string with a quote in it.

Anyway this function (along with probably some basic load/save .json file functions) should be included in the next update. Again I will let you all know about creating a mailing list so you all don’t have to use the forums anymore for updates.


Thank you for all of your hard works, I really love the new “Load” function and just one question see if you can help:

If it’s possible to access local imges outside of .pak file? since I’ve got my html file packaged inside .pak file I want to be able to replace images without re-package my game.

Thank you so much!

No, there is no way to access images on disk when loading an HTML file using the pak:// scheme. This would OBVIOUSLY be a huge security risk from a browser perspective, so it’s not going to happen. If you don’t want to package your game every time in order to swap out the images, why not setup a blueprint like this:

These are things you really need to start figuring out on your own or you’re never going to get anywhere. I don’t mean that to discourage you from making games, everyone has to start somewhere, but you need to learn to become RESOURCEFUL. I wouldn’t expect you to know about the URL schemes or image loading and the browser security and all that…but it never occurred to you to load the widget in two different ways based on development vs production…

There’s some new features being added to the JSON library for conversion between native UE4 structures. The best part is that these don’t just work for C++ structures but also for blueprint-based structures created in the editor. Here is a quick example:


These nodes are really easy to use. They have wildcards setup just like the SELECT node, so you just connect whatever structure you want to it and it will figure it out AFTER YOU HIT THE COMPILE BUTTON…



In the next screenshot an object is initially parsed from a raw JSON string and then stored in a variable called “Json Var” of the type JsonObject. Then the “JSON to Structure” node is called using this variable. It returns a structure of type MyStruct which is a native blueprint structure created in the editor. After that a structure is created of type MyStruct and then passed into the “Structure to JSON” node which returns “Object” of type JsonObject:

This update will also include the stripping of comments and trailing comments as mentioned in a previous post. It should be uploaded to GitHub within the next few days.

A new plugin will be coming out as well for JSON-based assets and settings files. This will be separated from the JSON library plugin as optional extended functionality that leverages the new stripping functions for a relaxed JSON structure in assets and settings files.