So I have a blueprint that can be placed in a level by the player, and when selected in game, opens a widget. Each blueprint placed then has it’s own instance of the widget, with its own unique info entered by the player. How would I save that info so when re-opened, the info for each widget is correct for its own blueprint?
I’ve managed to get the transform and class for the blueprint to save in the level, but not the widget that’s opened when the blueprint is selected.
If anyone has any tutorials or solutions, it’d be greatly appreciated.
I managed to implement what you said and I believe it worked. I can save the variables of the widget out and load them, as when loaded, I have a print string that shows the values saved and they’re correct.
The issue I’m facing now is how do I distribute the variables to the correct widget? Currently, when I load the save game, all the widgets receive the data of the last widget edited. So say one widget has a value of 1 and another 2, all are reloaded with a value of 2?
I’ve attached what I have so far. The first two are in the player controller, and the last is in the widget. Thank you if you can help!
The widgets should contain an identifier, perhaps an enumerator which also gets saved. When you load data, you create widgets based on that ID, pipe it in and the widget knows what to do.
In your example you do not create any widgets, though - it seems you’re re-use existing ones? You could associated widgets with enumerators in the map. Or have a dedicated widget manager actor that keep track of whose data belongs to whom.
Hard to advise without knowing the overarching architecture of what we’re making here. Those widgets could belong to actors for example, in which case it would be the actor’s job to re-create / repopulate its own widget data.
There’s too many ways to organise it all.
all the widgets receive the data of the last widget edited.
You’re using a double loop, you assign all widgets data to all widgets. It all gets overwritten over and over again. What’s worse, the GetAll nodes do not guarantee order. So this is totally unsafe and quite chaotic.
Ohh that makes a lot of sense, thank you for the suggestions. I’ll look further into using an identifier, as well as a widget manager. I’ll also try another way of getting the actor to create the widget data. Basically, I’m trying the make a top down game that allows you to place grain silos, and with each silo placed, has a widget that displays that silos grain details. Anyway, I’ll try this and hopefully update soon.
I believe I was able to get it to work using your input thank you! I’m not sure if I’ve done it in the best method but I’ve tested it and it appears to work.
So I did end up changing it so the silo blueprint manages most of the data and was able to give it an identifier using the number at the end of the display names (not sure if this was the best idea but seems to work). I then saved all the data from the blueprint, then on load recreated it and reset those variables which seems to be working.
I still probably could’ve set it up better and will have to find a way to be able to delete the silos in game without breaking it, but I believe that may be a question for a different topic. Thank you immensely for the help and guidance.
As mentioned above, GetAll does not guarantee array order. It may work now, but it may not work tomorrow, or it may not work after packaging, or it may stop working correctly as soon as you add one more actor or reload the scene. It cannot be relied on.
The widget’s job is to display stuff, not look it up:
the silo has the data
the silo creates and references the widget
the silo updates its widget
Generally speaking, it should be the silo that drives it all, and the widget merely displays what the silo asks it to. The rest of the script interacts with the silo only.
It stores a direct reference to its widget and updates it when necessary.
If you ever feel you need the Get(All)Actor of Class node to look up a specific instance, things have gone wrong. This is (almost) never necessary and a lot of alternatives exist - which method to choose is circumstantial, thouigh. What I suggested above is Direct Communication, where an actor stores a reference to another entity - here, a widget. If you wanted the widget to talk back at the actor who owns it, you’d employ an Event Dispatcher.
Ok I think that makes sense. I’m currently giving that a go but the part that’s confusing me is how do I call the custom event in the silo blueprint that sets the variables when a value is changed in the widget?
For example, there’s some editable text in the widget that can be updated by the player. I’m guessing I can then get the widget reference in the blueprint, get the value that’s been changed and set that in the blueprint, but how do I call it to set that variable once the text has been committed? If that makes any sense how I worded it?
This translates to: whenever Editable Text widget’s text is changed, notify the owning silo actor and set the variable. Actors and widgets already come with a bunch of delegates, as above. If the widget sends only text, this should be enough. But you can also add your own Event Dispatchers who can carry desired data.
how do I call the custom event
What happens in the game? What triggers the interaction with the silo? When do you need to do it? Generally speaking, you’d obtain a reference to the silo via:
Linetrace - player clicks the silo
Overlap - a fully loaded truck arrives at the silo
Hit Event - a tree falls on the silo
the GetAllActorsOfClass node - you need them all because you’re about to save their data
Ok that makes more sense. I’ve implemented what you’ve said and I believe it worked fairly well.
I’ve basically copied the blueprint image you sent, then when the player clicks on the silo blueprint with the mouse, triggers the updating of the widget info. If this is more what you mean?
Note that you can Show/Hide widget instead of Add/Remove from Viewport. Preferable in most (but not all) cases. Adding / removing is somewhat costly as the widget layout needs to be redone, and its Construct will fire every time. May not be relevant here, though.
Thank you so much! I’ve been testing it and it all seems to work well, so I can’t thank you enough! This also fixed my issue when trying to delete the actor as well. I did implement the idea of showing/hiding the widget too and seems to work well!