A Better way for UI Communication | Unreal ViewModels

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
if you want a better way to communicate data between game code and UI without cobbling them together and without using get all actors or widgets of class or using property binding which runs every frame then view models can be a better solution The View model plugin was introduced in a real 5.1 and its purpose is to allow programmers to work on game code without depending on a finished UI and UI designers to style and test their widgets without depending on a finished game system system view model is simply an object that holds the data the UI is interested in and notify listeners to any changes to this data in this video we are going to show different ways to create view models in both Blueprints and C++ and how to bind and lessen to view model changes by creating this simple example that shows the player health and inventur items two quick notes to clear out before we start we'll be creating our example in 5.3 and the plugin has seen lots of improvements in that version and the second is that it's still in beta so be aware not to ship projects with it until it's fully released with that out of the way let's get [Music] started once we enable the plugin we can start by creating our first view model when thinking about what data should one view model contain it is recommended that view model are small and modular so rather than having a single view model for combat data inventory items and player progression stats it's better to separate it into multiple smaller and manageable ones in our example we have a health bar so we can create a health view model for it to create that view model we can drive a child class from mbvm view model base then we add the variables our UI is interested in in this case the health variable and mark them as field no fies from this ring build if you are using blueprints this is what allows variables to notify the system that their values has changed if you are using an older version than 5.3 this can only be done in C++ as it wasn't exposed yet to blueprints in C++ to let variables notify the system when the values has changed we need a couple of things variables must be exposed to blueprints in order to be exposed to view models we do that by marking them with blueprint read or right specifiers then we need to mark them as field notifies this is equivalent to the ring bill in Blueprints and a last step we need to do is to manually call one of these macros when the variable or the fields value changes the C macro sets our field to another value and only CA the second macro to broadcast change is if the new value is different from the old one while the broadcast macro as the name says simply broadcasts that the field has changed it to notify listeners a good place to call these macros is inside Sitters of that field to create a CER or a geter for a field we can mark the field with the CER or geter specifiers these specifiers let the system look for functions named as sit or get followed by the exact same name of the variable and call them instead of reaching to the variable directly if you want to use custom names we can still do that by providing their names after the setter or getter specifi functions can be marked as field notifies as well this can be useful when you want to make some calculations conversions or formatting when a variable Chang for example calculating the percentage of the health variable when it has Chang there are some conditions that must be met in order for a function to be allowed to be a Feld notify the function must be pure and constant it must take no arguments and it must return a single value now let's get back to the editor and see how we can initialize our view model and use it at TR time here we have a simple user widget with a health bar and a less View for the inventory items for the widget to fetch or create our view model we need to open the view models Tab and add our view model to it now our view model is linked to this widget but it is not yet initialized there are five methods to initialize or create a view model create instance creates a new view model instance with each instance of the widget that's lots of instances this is useful when we want each instance to have its own data and not be affected by other instance we can still manually control the creation of the view model after the initialized call back in C++ or the uninitialized event in blueprints the system will only create a new instance if the view model was not set and that happens between the pre-construct and the construct events now for our game code to reach the view model at trun time we can use some hper functions through the mvvm view model subsystem and reach it through the the second creation method is manual this method means that the view model object is initialized later on by us whether inside the widget or anywhere else for example we can create the view model once in our game code and when new instances of the widget are created they can be assigned that same single view model one use case for this is if we have multiple widgets interested in changes to our player Health maybe a game end screen a health bar and a damag UI effect they all should be using the same Health variable coming from a single view model the third creation method is the global view model collection this is the one I'm using the most it totally decouples the widget from the game code by adding a global collection of view models between them this is a game instance subsystem that is easily accessible from anywhere to use it we can access the collection from anywhere and add the view model instance to it the context is very important here it must match the one we sit inside the widget another thing to note as well is that the instance of the view model will be valid even if we transition between levels as it's stored inside the game instance subsystem to fix the view model from anywhere in our code base we can call theine view model instance function from The View model model collection a good example for this is a settings or an accessibility options screen where data is coming from multiple places the fourth creation method is the property path this one is useful when we know where the view model object exists and instead of the view model instance being sent to our widget our widget goes and fetches it in this example we create a health view model inside our player character and store a reference to it now to Fitch it from the widget we can write the path from from the widget to the view model which will look something like this the git custom player character function is a function we made inside our widget to get our player pawn and cost it to our custom character the last creation method is the resolver object this was added to 5.3 and it is very useful it allows us to pitch or create the view model with our own logic and implementation by creating a resolver class and overriding its create view model function now our view model is initialized the changes are being brasted at run time but no one is listening to listen to changes in a view model and change or UI based on that or act appropriately we can use view bindings but to avoid confusion with the Legacy binding system let's disable it through the project settings this will let the compiler warn us if we have any use of the Legacy binding system there are multiple ways to create bindings the fastest is to drag and drop view model properties on the wedged properity we want if we open the view bindings tab now we can see a binding created for us the arrows indicate the direction of that binding are we listening to changes in the view model making changes to it or both we can also use convergent functions if for example The View model has a string variable and we have a text block inside our widget we can use a conversion function to convert from string to text for example there are some caveats when using view models for example arrays and view lists are not normally accessible in view models if we have an array of items that we want to bind to a list or tile view it can be little confusing to achieve it since if we try to bind to the L views add item or remove item functions you will need to create a field notify function in our view model that takes an item as an argument and that violates the conditions for making a field notify function one way to go about it is to bind The View model's items array to the list views set list items function now when a new item is added or removed from our view model array we broadcast that change and our list gets updated the second caveat is map properties if you we have a map property in C++ that we want to set its value using the C macro this will lead to an error as the macro needs to check if the property has changed or not but the map property doesn't override the equals operator one work around this would be to wrap or map variable with a struct and override the structs equals operator these caveats or minor ises are good to know about before using view models and I'm sure they are getting addressed in future versions and the plugin is still in bit so once again be cautious when using it project files can be found in the description below and if you like this content consider supporting the channel through patreon thank you for making it to the end of this video this was arm and if you are interested in more UI videos consider checking this one
Info
Channel: AmrMakesGames
Views: 1,237
Rating: undefined out of 5
Keywords: game dev, game development, viewmodel, umg, game ui, unreal, unreal engine, user interface, ui, mvvm, view model, ue5, ue4, unreal engine development, HUD, game menu, gamedev, ue5 best practices, umg widget, unreal hud, unreal ui, unreal umg, unreal widget, widget blueprint
Id: 93NTeqTiXIw
Channel Id: undefined
Length: 10min 55sec (655 seconds)
Published: Sat Feb 10 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.