UI Architecture Best Practices?

So we have been adding UI elements over the past months and I am starting to think we need to actually think about how everything communicates with the UI and vice versa. Right now, calls to widgets are just added wherever they are needed and when you go back and look at a lot of these calls it is not necessarily clear what they are calling to and why. It is entirely decentralized, so I have been thinking it might be good to have all the UI bits talk to a controller to make a lot of these tasks more streamlined. And also so you can peruse over a single blueprint and get a better idea of how everything ties together for the UI.

So the idea in my head goes something like “Blueprint A calls an event the UI Controller to open Window B, and the UI Controller knows that Windows C and D need to be closed and takes care of all of that without Blueprint A getting involved”. Does that sound like the right direction?

Does anyone have any tips for designing a very robust, flexible, and understandable UI structure? I should probably mention that the UI requirements for a turn based strategy game are going to be kind of insane compared to what many of you have in mind for your projects… :slight_smile:

I’ll be interested in hearing other people’s solutions to this as well. I ended up doing something very similar to what you described above. I already had a global event manager, so I created a UI manager and created a class of events to request modal dialogs, etc. Most of my dialogs have standalone functionality, though a few require some data to be passed, which I store in the UI manager, and a few are chains such as confirmation dialogs, etc. Then, when I need a dialog, I just request it via an event and I use a struct to specify which dialog island/chain to open as well as pass a little data if needed. This is all from C++, so I already have a struct specifying all of the available dialogs just for convenience. It works well, but right now the implementation is somewhere between hacky and robust. I think the architectural design is fine, but it grew somewhat organically so I need to go back and refactor a few things.

For my next project, I may go full Slate in C++ instead of a mix of C++ and UMG. Gwenn’s Helium Rain UI is gorgeous and is very inspiring.

What kind of things have you felt forced to handle in C++ instead of UMG/Blueprint when it comes to UI?

I have a feeling that the core logic can easily be handled in Blueprint, but there are probably plenty of edge cases where you can’t do a generally basic thing because some key bit isn’t exposed yet. I hope to create a good list of such things and pass on to Epic as I dive into this.

And I imagine there will always be a place for C++, but would like to prototype as much as possible before going that route.

It’s actually the other way around. My whole project is C++ with a very small amount of blueprints, the majority of that being UMG. The visual designer is nice, and while node-based logic is ‘nifty-neato’ and I do like it, it gets a bit messy fast and I prefer code, so even my widgets tend to have C++ parents. Also, I find creating enums and structs in blueprint to be really awkward. However, since that’s what I do for a living, that makes sense for me. For most normal UI’s, I don’t think you’ll find any issues going with a full blueprinted UMG solution, and the technique of using events and a central controller works just fine in blueprints as well as code. I think you’d be forced to go to C++ and Slate only if you wanted to make custom widgets or extend the UI to do something it doesn’t do out of the box.

EDIT - Just to be clear, I didn’t intend for this to be a C++ vs Blueprints discussion. I was just noting the architecture that I used to organize my UI and while I have done it in C++ for the most part, it certainly can be done in Blueprints as well. The general idea is the same.

Yeah that is what I was thinking/hoping too. Should be able to make it all in BP/UMG and then if a specific functionality is needed it could be added by itself in C++.

Going to start rewiring everything to run off a UI controller so I will post here if I run into any issues or have other relevant ideas.