#about GUIDs
1 messages · Page 1 of 1 (latest)
@rain gate I'm going to create a thread here so I can reference back to it if needs be
That works too 🙂
reposting your last message so I can remember it
"The implementation of it can be on "Begin Play" of that actor, you read the Map from the save game object and if it finds the GUID in the Map, then it manipulates itself based on the data in the map for that particular GUID. If there is no data present, then that item can behave as it was just placed in the level. You would likely need some way to indicate whether or not the actor should be destroyed in this case, so that the actor can remove itself from the level if it was destroyed at runtime.
Saving then is just adding a value to the Map with the desired data.
Dynamic items spawned at runtime would need their own map which would need to contain data about each of the objects, like what their class is that should be spawned, their location, and any other properties - you'd probably want a custom structure. You'd use begin play of say your game mode or game state to then read this separate map, loop through the keys, spawn the objects assigning their GUID to them based on the map key, and then reading their value from the value of the Map and applying it to the actor that was spawned. Upon destroying one of these dynamic actors, you would want to remove the GUID from the Map in your save game so that it would no longer be loaded."
@rain gate so where would I assign the GUID? Is that on beginplay too?
Depends on the object.
You probably want one to be assigned in the construction script if there isn't one already assigned to the object (i posted this screenshot before) - this ensures placed actors are uniquely identified.
You probably also want to have an exposed variable that can assign it so whenever you spawn an actor you can feed it a GUID. This then handles assignment of a GUID for any dynamically spawned actors.
I see, something I got before when I implemented this is, I had 4 copies of an ORB object and 2 copies of a SWORD object on the map, only one of each of those generated an actual GUID when the level loaded
Case 1:
Placed Actor - GUID is assigned when it gets placed automatically VIA construction script.
Case 2:
Dynamically Spawned Actor (existing for the first time) - Spawns Actor with the GUID variable field left blank on the spawn node.
Case 3:
Dynamically Spawned Actor (loading from save) - Spawns Actor with the GUID variable fed in through the spawn node.
the SWORD and ORB each are child actors of a test item, that test item had the code on its construction script and it would add them to the map
I then had a keys node come out of the map, did a for each loop, and on a key press I had set up it would read out every GUID on the list... and despite there being 6 items on the map, it only printed 2
Can't comment on child actors. I've never used them.
@rain gate so, it's not generating GUIDs at all... I have all of this set up on the construction script of the items and when I launch the game none of these print strings are coming up
Not sure if the print string can work in construction script.
What is important is that the GUID is being assigned a value only if no valid GUID exists.
First image: Item has a GUID variable exposed.
Second Image: Code showing a GUID being set on the actor. HOWEVER, if you set it up like this, then whenever you change the object a new GUID is generated (so like, moving it arond the scene).
Third & Fourth: Showing the GUID is different in this circumstance just because I moved it.
Fifth & Sixth: Showing what happens if you check if the GUID is valid first before assigning a GUID and moving it.
ok so, I'm running into a problem I ran into before...
@rain gate all the copies of the same item in the level are sharing the same GUID, they aren't generating new ones
If you're duplicating objects then it can end up copying the value of the GUID as well. You'd need to ensure the GUID is cleared so that they get their own GUID.
how would I do that?
like is there a way to automate it?
Automating it would require you have some means of knowing whether a GUID is in use already and regenerating if so.
Otherwise you'd have to click this back arrow thing and it'll "reset to default value" which would trigger the construction script part again.
If you weren't stuck using blueprints, you could definitely have something set up in C++ to automatically reset when an object is duplicated.
there is one way I can sorta automate it in BP
have all the items in a folder in the map editor, right click the folder, select all children then click the reset to default next to GUID, it scrambles it for all selected items
it's just something I'd need to remember to do after editing a level
Sure.... But I think that would only work if they're all the same object type. And you may not necessarily want to do that later on in development as you could end up ruining people's saves as the GUIDs aren't what they were in the past.
You basically only want to have a GUID on any particular actor modified once.
thing is... my project has C++ enabled because I needed it to get rid of that annoying "tab cycles between ui elements" shit UE5 has in by default.. so I can add C++... as long as it doesn't fuck up my existing blueprints and you'd be willing to give me the code I'd be fine just plugging it in there
just as long as I don't have to code it myself I'm good XD
like I'm not averse to the idea of having some C++ in my game, I'm likely gonna need it, but I want to keep it to a minimum so if something breaks, I can have a much easier time figuring out what's wrong instead of scrambling to figure out code I know nothing about.
You'd basically have to override the PostEditDuplicate() function in the actor classes that you want to have a GUID, which means you'd need to have C++ base classes for any actor classes you'd intend to use and then reparent your blueprints to use them. It's more work than I'm willing to provide.
ok. I'd just have to remember which are the new items then and scramble the GUIDs.
so that brings me to my next question, now we have the GUIDs working and a method of storing them, the whole thing of finding the item's GUID and deleting it if it's not on the list happens in an item's beginplay right?
For placed items, yes.
how would I separate out what are placed items from what are spawned during runtime?
You can have a bool set on the actor for when it is dynamically spawned. Set true only when you use "Spawn Actor from Class"
also the other major question here is, what about inventories and stuff because sure this establishes what actors should exist and to an extent you can determine where, but what about containers and their contents? Would I still use my struct for that?
A Map acts as a container. It can hold the identifier and the values for that identifier.
Not all actors will have the same storage requirements, so a single structure likely isn't going to handle everything you may possibly want to save.
So as long as you can identify something with a GUID, you could potentially make a separate container with a structure that contains the values it needs.
So an inventory, yes, could hvae its own GUID assigned to it, but you wouldn't look up that GUID in your "Spawned Actor Map" you'd store it in a separate map "Inventories". The structure of the data could contain an array of structures that then have details about each of the items within that inventory.
so would that be instead of it being a GUID to BOOL map it would be a GUID to Struct Array Map?
can you assign GUIDs to components?
And then you have different Maps with different Data for the GUIDs it holds.
Probably. I don't think they have construction scripts though.
so in this case, where am I putting the destroy actor node?
I have the list of actors in the level, I've pulled the spawned actors list from the save file
would it be if either of them are false? because surely if it's an item that's found and it's on the list then it's part of the level right?
because the idea is this is the list of items in the level, the GUID is removed from the list when the item is destroyed, so if either are false then the item should be destroyed because it's not on the list... or am I getting this really wrong
Spawned Actors contains what? Placed items?
yeah, in the item's construction script it has a GUID and when the save button is hit all items with a GUID are added to the map
Ok, I wouldn't call that container "Spawned Actors" then, these are "Placed Actors".
In this case the Destroy Actor node should be on the last true.
1st True: You found the GUID in the list.
2nd True: The bool is set for it to be deleted.
If either one of those are false, you don't want to delete it.
When you pick up the item, you are:
Adding the GUID to the Map
Marking the bool within the Map to true, denoting you want it deleted.
Destroying the Item
So then when you are Beginning Play on that actor:
You're looking to see if the GUID is there.
If it is, checking if it should be destroyed.
If it should, you're destroying it.
This gives you the continuity as you've saved the state of whether or not the item should be destroyed.
thanks
I'm just trying to find where the hell I put the code to destroy the item on pickup so I can add some extra to say "also remove its GUID from the save data list"
Why would you want to remove its GUID from the save data list at that point?
would you just set its bool to true to set it as a picked up item?
how do you change the bool on a specific GUID entry?
You re-add the GUID to the Map with its new data.
First exists (in editor): GUID is created.
Begin Play Starts: it can't find its GUID in the map, so you program to act as-is, no further changes.
Some time later (even several play sessions later): You finally pick that item up. It adds itself to the Map, marking that it was picked up. You destroy the object.
Next Time the Begin Play Starts (could be several play sessions later): It finds its GUID in the map, it sees that it is marked as picked up. It destroys itself.
so I just had to redo a bit of internal code but I think I have it working for the most part... I'm sure I'll have more questions later when it gets to saving inventories but for now I'm just going to clean this up
thanks for the help
@rain gate actually sorry to bother you so soon, when spawning an item, whe's the best time to set dynamically spawned? like what would be the load order here?
Will any code executed on the spawned actor from its return value node activate prior to beginplay occuring?
You probably want it as an exposed variable that you can then set on the spawn actor from class node. That way the value should be set by the time begin play fires.
slight problem with that.... Whenever I drop an item from my inventory, it could be any number of item classes... so I spawn the actor based on the items data from the inventory
I think I got a solution, from the item data item class I cast to the parent class that all the other items come from which then gives me the proper node on spawn actor, I tested it out and items I dropped did have the check box
Yep, that's basically what you'd need to do - ideally your "Item Data" would by default be using the appropriate base item calls that has the values you need for all items.
@rain gate so, ran into another head scratcher. How do you assign a GUID to a player character? They get spawned in every time you run the level which means every time you play you get a new GUID
You wouldn't bother with GUID for a player character as there should only technically be 1. You'd just save the data about the character and load it as needed.
how am I going to tell the player's inventory apart from the containers then? They all have the same inventory component on them
You don't store it as a GUID either.
so, where do the container inventories get saved?
also this whole thing is becoming such a mess... please tell me this save system is the hardest part of making an RPG
like this is just the item code for saving and loading..
granted I went.. probably further than I should have done and implemented a system where it saves the position of each item during a save event and loads them again when you load.. so you can throw an item across the room, save, exit, reload, and it's still there
If you want to use a common component for storing inventories, you can absolutely have the player's inventory done in such a way too, but then you have to figure out when it is best to give it a GUID but I don't think it really makes sense to as your player character is a unique entity, as is your player's inventory, and this system is designed to save things about things that aren't unique.... Like enemies where you may have 30 of the same type of mob spawned in at random times and places, or many hundreds of items that could be strewn about. This means for unique things where you know for certain you only want to save a single time, you may want to use a child class of your inventory component that you use exclusively on your player character that handles saving its data differently - it could literally be the exact same thing just with an override to its save and load functions so it reads a specific variable in your save game.
Saving and loading data is a mess.
It's about taking all the details out of something, storing those details, then reading those details again, and resetting that something back to its state it was based on those saved details.
Don't cross execution lines.
?
The first time this code executes, if the first branch is true, the cast isn't hit, but you're pulling off the cast for a value.
ok yeah that fixed the issue I was getting
so for saving inventories, would it be an idea to have it set up so that in inventory component, if parent is player character save to an array but if parent isn't player character save to a map of arrays?
the map of arrays being the inventory and equipment of enemies, npcs, contents of chests etc?
Eh... I wouldn't say I'm fond of that solution, only because it puts emphasis on checking if the owner is a controlled instance of something.. It's not necessarily expandable, and doesn't cover the scenario of what if the player isn't currently possessing the character but you need to save?
That's why I suggested the child class... Basically would keep everything the same, just overide how it saves and loads itself.
I guess, so what's the alternative? Because saving inventories is the biggest issue I've been wanting to cover this whole time
so how would the child class work?
because at the moment the inventory is a component.. I'd have to re-rig the entire inventory system to make it its own class..
no
You create a child class of that component.
It would end up having all the same logic involved.
What you'd want to do is create functions in the parent component for saving and loading.
You change those functions in the child so it does something different.
You then use the child component on your character.
how do you create a child class of a component?
Right Click on the Component.... Create Child
ok, so how would I store the actual data? like if there's a chest, I open it, I loot its contents, I hit save, how do I tell the game to save the data for both my inventory and the chest's inventory using this?
You get references to the inventories involved and call their save function.
they don't have any kind of save function at the moment though that's what I'm asking
Create one.
In the standard inventory you'd use the GUID > Save whatever data you want save in a structure.
In the player inventory override of the save function, you'd just save the data in a single variable of that same structure, probably named "Player Inventory"
Loading then would be....
Standard... Read the GUID map for the GUID of the inventory and read the structure and populate the inventory component.
Player.... Read the Player Inventory variable and populate the inventory component.
so.. I replaced the inventory component on the player character with a child class of the inventory component.. and it completely broke everything
I can't pick up items anymore, the inventory has no slots, and I get this error
pretty much all the object interaction data was built into the inventory component in the form of functions...
If all you did was relpace the inventory component on the player, then this error indicates that you were directly referencing the player's inventory in the inventory component itself, or within your item class.
Like, doing a cast to your character's class and getting a reference to the player's inventory component.
I think this may be part of it
this is how interactions get started
like, the interactions, the population of the inventory, sending out stuff to the item data so it can be deleted when picked up, putting the widgets on screen, all of that is handled in the inventory component
where does it take you when you click on these links?
to this "is valid" in the middle of the screen
this is where all the item data is
So there's the problem, you're specifically referencing the player's inventory.
yeah well that's on the interaction,
The input to that interface should just be an actor. You'd grab the component of class (inventory) from the actor.
so basically that sits on the items to say "if I'm interacted with go to player's inventory and delete me"
If you want to keep it as is so you don't have to refactor more, then just do a grab of the component of class (inventory) from the player character reference there.
would this work?
Should, yes.
I just ran the game and it doesn't seem to be throwing any errors
so, when it comes to child classes of the inventory system, would it make sense to have 1 for player and 1 for everything else, or should I split up enemies from chests?
since enemies can equip and consume items would there be a requirement to need a third child instance or would just the 2 be ok?
I suppose in a way an enemy is just a chest since when you loot them they are either dead or it's pickpocketing..
Possibly, that's part of the design you'd need to think about. Is the inner workings of the inventory going to work effectively the exact same way as a chest as it would being on an NPC? If the answer is yes, then you probably don't need to.
I still need to refactor a lot of this inventory system honestly.. and splitting up the player from the containers might be a blessing because I wanted to remove the slot based system and have it be weight based
there's already a system in place for # of inventory slots, and it's on a scrolling box so, would you just look for an open slot, and if there isn't one generate a new one and place the item in there?
How you want to handle what your inventory is displaying or holding isn't really something I could help you with. That being said, this is also diverging from the original intent of the thread.
fair enough. I'm going to sleep since it's like 8:30 in the morning and I've been awake since yesterday. I'll likely run into more issues setting up the whole GUID system for inventories so, I'll ask here when I do.