Save Tamed AIs

Hi!

I’ve been trying for a while now to save only the AIs that have been tamed. All tamed animals, have a struct with information that says it state is tamed [enum] and who the owner is.

I would love to be able to respawn only these AIs that have been tamed, at the start. The AI system is set up in a way that no AI is spawned at start, since player has to go within a spawn zone for that to happen.

So how can I find what animal was tamed, save it to a save game, then spawn it again at the transform it was in before the player exited the game while also keeping its “tamed” status?

I’m getting the hang on save systems, but I’m still having lots of issues when it comes to saving structs from multiple actors.

Also want to mention that this struct is set inside a component.

As you concluded the save games are solution here. Some advice for the saving would be to have one array of some global struct that has all the information needed. That global struct would have the AI type that is tamed, the owner, his transform when the player leaves and any extra details. If you have to save the same AI multiple times, you can have save an index of its position in the global struct array and then open the save game, change his details and save it again. Treat the save game as any object you have in the game when it comes to accessing and changing the variables, the only difference is that you need to open the save game and use that reference to edit it and save it.

I see! I think I can get that to work, but how would the engine know what kind of AI to spawn on start? Sorry, I’m just trying to understand it more so I can understand if I go wrong! :smiley:

You can create a variable for that. It can be a class reference or an enum. The idea would be that when the game starts, you would open the save game and read that variable and determine what AI type to spawn.

Okay I’ll give it a go soon! :smiley:

1 Like

Okay so I managed to save the AIs transformation and class, but Im not sure on how to proceed.

Right now it saves all the AIs. So if I started with 2 AIs, then go and tame 1, save, then when I reload I suddenly have 3 Ais. And so forth for each time I load the game. I’m not quite sure if I understood how to only get the information from the AIs that have been tamed.

Hey there @Skylene1! Whenever we get stuck on things like this I always like to zoom out at the bigger problem and afterwards drill down to the specifics.

So let’s start by listing the goals.

  1. Check all AI to see if they are tamed
  2. Save the tamed AI’s transform and stats.
  3. On load, place the AI at the correct location with the correct stats.

So let’s start with 1, the best way to do this check is not to check every single AI in the scene on save, seems like a waste. A better idea would be to when they are tamed they should be added to a “To be saved” array. This eliminates having to loop through all AI and look at their tamed stat. The only downside is if some AI start out tamed then you’d have to make sure to add them to that list or loop through all.

Next actually saving the AI and their stats struct. Looks like you had already done that so I won’t get into too much detail, but basically you want a reference to the class, their stats struct, and transform. Then on load place them where they should be.

Third, load the info, spawn the AI class, change the fresh ones stat struct, then spawn it at the transform like you’ve done.

Oops, we now have multiplying animals! This is because your spawning mechanism has no clue the AI it’s about to spawn has previously been tamed. This is actually usually a different system but can be dealt with the same way, but it would influence the entirety of your spawning logic. As of now the AI spawning is likely just guaranteed right? Well now it needs to be conditional. There’s tons of ways to do it. But one of the easiest is when you send the tamed animals to the “To be saved” array, there also needs to be info sent to your spawning mechanism. You could use location references, IDs on your AI’s and reference them when spawning, or even pass an array of tamed actors and disable spawning at their start point. It all depends how your spawning system is laid out.

Hello!

Mind if I ask what you mean by “load the info, spawn the Ai class, change struct and then spawn it on transform”

Why would I have to spawn it twice? (Just asking again to see if I can understand better how others think!)

I currently have it set like this, but it still doesnt save the stats it seems…I’m not sure what im doing wrong :sweat_smile:

the actor array gets actors added when the taming has been successful, like you suggested!

EDIT: Seems like I was doing it correct, but something else was overwriting the struct at begin play. Putting a delay before the variable getting set in the component, gave the load system time to load the right stats first!

Also, I had to save the variable of the actor array that I added to whenever an animal had saved. When I hadnt, If I had tamed more than 1 animals, it would not load the stats of the others.

1 Like

No worries! I’m always vague when speaking from a general standpoint. It looks like you’ve already got the loading mechanism in place and functioning, it’s exactly how I’d do it so no notes there, I don’t see an issue with the Saving/loading functions themselves.

So the issue remains that the stats aren’t transferring but it’s creating the animals? So either the data coming from the save file isn’t coming in. May I see your Load slot mechanism?

I managed to fix it, so theres no more issues! :smiley: It was like I explained in the solution post, that some other code was overwriting the loaded data. But its good to get an insight in it from someone else too.

So thank you so much for taking time to help!

1 Like

Sorry to ping and reopen this thread, but I figured I’d do it since I’ve noticed an issue I didn’t see earlier when testing this, and I didn’t want to make a brand new thread since all the info is already here!

The saving and loading works if I save to a slot for the first time and load it. But if I save to the same slot again, it gives a bunch of errors and no longer works… I’m struggling to understand why. The errors come up as this when I load the save:

and this if I try to overwrite the save:

Now looking back at your post @SupportiveEntity , I see where you point out that I should look at three goals, and the first one being that I should add the tamed animals to an AI. I have added the AIs to an array the moment they have been tamed. But you also mention that “The only downside is if some AI start out tamed then you’d have to make sure to add them to that list or loop through all.”

I’m assuming that might be the issue, but I’m not quite sure how to go about this information

No worries! Took me a bit to get reacclimated. So it looks like the Add node is trying to access a tame that is not viable any longer. Are you changing level/exiting when this is happening? We could put valid checks across this to verify what it’s accessing is available, but that won’t tell us why it’s failing. Could you have it print out the index and name of what it’s trying to use each save and load? This will tell us if it’s trying to access something that isn’t supposed to be there, if we need to sanitize your inputs/outputs better, and we may need to force clear the attached array each new save.

1 Like

Hello!

I have gone ahead and put some print strings to check that the array contains something, and when I do the very first save, this comes up as -1.

However if exit the game and load up the save and save again, it says 0. If I dont press escape to exit the game, I my pause menu. When I’m saving, I use the pause menu, but I only change maps when I exit via the menu, to then load up the game again, because the main menu is its own level.

The “Local Tamed Animals” Array variable is called before this save and load event, and they look like this:

If I just load into the save again a second time, The tamed animal that is supposed to spawn, is no longer there and thats when the first error message in my previous post shows up. The print string on the “Load Tamed AI Array” on the other hand says 1.

I have noticed on the other hand that clearing this variable:

image

Before I later set it again

Seems to be the reason that the AI disappears.

I tried to tame another animal in the save that the AI has disappeared in, and on the “Save Tamed” event, the print string to “Local Tamed Animals” Array is 0 again.

But the print string in the function “Save Tamed AI Array” Now shows 2.

Now midst the trying, I noticed the print string to “Local tamed animals” is 0 because I’m using the wrong node. Instead of “Find” I should be using “length” i believe.

Having changed that, and also gotten rid of the “clear” node, the print when saving is suddenly up to 7, although I’ve only tamed two animals.

So with the “clear” node plugged in again, when I try in a completely new save, the first time I save the print node from “Local tamed animals” length node is 1. If I exit, load the save, the animal is still there and the print string is still 1. I tried to exit again to triple check, and now the animal is gone, but the print is still 1.

I then added two print strings by the add node in the save event:

The length print is 1, while the add print is 0 (which my guess is that is because nothing new was added? I just went into the save with the disappeared animal, and saved again, nothing else.

For the loading aspect, when I load into the save, I have a print string here to check the length of the saved Array:

image

It prints 1 when loading the save with only one animal tamed. If I tame another animal, both arrays says that it contains 2 items when saving and when I load, the array “Save Tamed Struct” length prints 2.

I’m not sure if all this was useful, but I’m writing down everything I observed just in case! :slight_smile:

Now I’m not 100% sure how to print the names from the arrays, so I havent done that yet.

I also went ahead and tried to put some “is valid” nodes as you suggested.

I set one in the “Save Tamed” function, since this is where the set variables are referenced:

It seems that when loading the saved game, it runs invalid. Then this error pops up:

And when clicking on it, it directs to “standard macros”. So its definitly something here that makes it unable to retrieve the Taming component, but I don’t understand how that is when the “Local Tamed Animals” index is the same as the amount of animals I have tamed. The variable is set to the parent actor of all my AIs and with an object reference.

The is valid node, though, helped get rid of errors in the loading aspect. So It has to be the saving that is failing, and thats why the AI is disappearing, because it doesnt have the AI class info on what AI to spawn.

Edit: I tried to put and is valid node directly from the for each loop and that one seems to fail too.

It’s definitely an issue with the saving, but the valid checks are just fail-safes so the loading will have an issue as well. So we’re now going to have to focus on the saving. Might have to put break points through each piece of the save function and verify that the data is exactly what it should be at each step. I know it’s tedious but when working with arrays of structs it can be necessary. Remember to set up watch points on them and start the debugger. I’ve looked over it a couple of times and it looks like there shouldn’t be an issue with the way you save this struct, you save all this via the save slot system right?

Yes i save to slot :slight_smile:

It seems to somehow always fail here so its not the struct array

image

and this array is the one where the AI gets added to when its been tamed, then I save it like I showed in the previous screenshots, before I go ahead and use the save tamed function.

Could it be overwriting the variable somehow? Like a new ai is added to the array once its been tamed, and everytime the player manually saves, it saves the array the ai was added to. And that works perfectly the first time. But if the player exits, reloads the save and saves again, thats when the “Array element” of the for each loop is invalid.

I looked over the system again and decided to try a new approach.

Instead of saving what actor was tamed, and add it into an array with object references of the actor, I did “Get all actors of class” and sent it into a for each loop. There I got the node “actor has tag” and set the tag to “tamed”. And then ran that through a branch, so that if it was true, it would be added to the save array, if not, it wouldnt be added.

I didnt know you could set tags during runtime, so since I found out, I created a name array variable on the parent class called “new tags” and copied all of its normal tags into the array, and added a new one named “tamed”.

So when an AI would be tamed, instead of adding to the object reference array, I’d get the “new tags” variable and set the “tags” variable of the actor.

I did also after the branch check to “actor has tag”, save the variable “new tags” so that in the event “load tame”, I could set the variable to the new variable again, so that if I save again, the already tamed ones will still have “tamed” in the tags.

I did have a small, and weird issue though, that every time I’d save and load the save, the animals would grow in size. All I did to fix that, was to split the transform that I’m trying to save, and only plug in the location and rotation.

Another issue I had when testing with and without the “clear” at the start of save tamed, was that without it, it would spawn multiple AIs even though I had only tamed one animal, so clearing definitly needs to stay there.

Thanks again @SupportiveEntity for the help, I’ve learned a lot thanks to you! :smiley:

1 Like