Over the past month we’ve been working on a new approach to UI in our game. We need to get our UI efforts underway now, and UE4 currently lacks an adequate system for doing 2D UI.
We’ve decided to build a new system we’re calling “UIX,” and we wanted to share this here to open a discussion with Epic and the community. Maybe this will be useful to some readers, and maybe this will help communicate to Epic what our team is really looking for in an integrated UI development system and help guide their efforts.
We’d like to share our requirements for the UI, our evaluation of the alternatives that led us to building UIX, and a description of how it works. This system wasn’t difficult to build, and this kind of functionality is something we fell should be part of UE4 in some form.
Our requirements are:
- The UI system needs to be user-editable with a more-or-less WYSIWYG layout editing system, as well as allowing us to edit the layout in some sort of text-based format.
- It needs to be fully integrated with Blueprint and allow us to do most of the work of setting up a UI in Blueprint and the layout editor, while also allowing us to do whatever we need to in C++.
- It needs to give us full control to allow us to do fades and sound effects and color/position animations trivially from Blueprint, and also be extensible enough support more advanced UI animation effects (shimmers, glows) with a bit more work.
The alternatives we considered:
We looked at Scaleform, but couldn’t find enough info on pricing or even the state that their UE4 integration is in right now. We’re also concerned about pricing and how well it will integrate with UE4.
We also looked at Slate, and implemented the first pass of our UI system with it, but we concluded it wouldn’t work for us in the long run, because:
- Slate currently has no interactive UI editing tools.
- Slate isn’t compatible with Blueprint, which is annoying since that’s where we want to do most of our UI work. Slate forces you to do everything in C++, so every change is a recompile.
- Slate forces us to write all sorts of little callbacks to handle mouse and keyboard events and change a widget’s position at runtime, and this is often the least effective way to do things.
So Slate is out, and even if it gets nice interactive editing tools at some point, we can’t use them right now since Epic hasn’t announced anything about them yet.
Epic is also working on Unreal Motion Graphics, but we don’t yet have any specifics as to what this system will do or even if it will do anything like what our game will need.
How UIX works:
The UIX system currently supports:
- Interactive in-game UI editing with the mouse and keyboard. You can mouse-over an element in-game to change its name, tweak its position with the mouse, change its sort order, or change the texture it uses. Yes, in-editor editing would be better, but we’re not willing to modify engine source files at this point.
- Text files. All UIXFrames save out their layout data as “.UIX” files which are trivially editable by hand, as simple lists of elements with their names, sizes, positions, and texture indices.
- Source control integration. UIX doesn’t yet automatically check files out for you the way I’d like, but it does respect the read-only status of the UIX files and won’t let you edit a frame unless the associated UIX file is checked out.
- 2D rendering through Canvas. 3D UI elements aren’t supported yet.
Here are some screenshots of the UIX placeholder UI for our game so far:
Here’s what the interactive editing mode looks like:
And here are two screenshots of the Blueprint graphs for two of these UI elements:
Finally, a .UIX layout file looks like this:
The core functionality of UIX relies on a C++ base class AUIXFrame. AUIXFrame holds an array of textures and a list of ‘elements’. An ‘element’ is like a widget: it draws a texture (based on an index into the texture array) inside a certain user-defined rectangle in 2D. It’s intended as a logical grouping of UI elements that are closely related and should show or hide together.
It exposes basic Blueprint events for responding to mouse enter/exit, mouse-down, mouse up-and-down, mouse click abandoned, etc, and functionality for making elements and frames fade in/out, show/hide, animate their colors and positions, change their texture indices, and so on.
To make your own frame, all you need to do is:
- Extend a class from AUIXFrame in C++ and extend it with whatever C++ - specific functionality you need.
- Create a new actor blueprint derived from that C++ class.
- In that blueprint object, specify the textures that the UI elements in that frame will use.
- Run the game, hit F9 to enter UIX editing mode, mouse-over the UI elements you want to modify, and stretch, move, rename, re-order, and re-texture them to your heart’s content. You can also add and delete UIX elements to the frame by hitting Insert and Delete on the keyboard. Hitting F9 automatically saves your changes to text-based “*.UIX” layout files.
- In your Blueprint use the Blueprint events and functions provided by AUIXFrame or any custom ones you defined in your C++ subclass to define its behavior.
- Add an instance of that Blueprint actor, either by dropping it into the world or by spawning it dynamically.
I’m tempted to post the source code here, but it requires extensive integration with the player controller and the HUD in order to draw and intercept mouse events properly. I’m willing to do it if there’s demand for it but there’s a ton of integration work involved, and of course I can’t make any guarantees about support or reliability.
There also some issues we’re currently working on, such as the fact that the *.UIX files don’t get packed when you package the game. Epic is looking into adding support that would allow us to do this, but right now, it’s not possible without modifying the engine source.
We’re also working on improvements to UI scaling for different resolutions. Right now, we’re simply directly scaling based on the client view rect vs. the client view rect when the frame was edited, but in the future, we’ll either make their positions and sizes relative to other UI elements (a bit like Slate does) or allow custom UI setups for different resolutions and interpolate between them as needed.
I’m also hoping to add support for mouse-wheel zooming in edit mode in the future to allow you to fine-tune the look of the UI, along with some positioning guides for when you need to move or resize an element relative to some other existing element(s).