Passing variables by game instance

I set up messages to print on string in case of failure to cast, but instead the event never fires from game instance at all
I think you mean that the cast to GameInstance does not fail and the failure string is not printed. This behavior is normal since you are casting to your GameInstance and accessing it correctly from your actors.


Can the game instance not access actors directly in the level?
A GameInstance can actually access the actors in the current world/level, which you are also doing correctly.


I think the issue is that you are saving references to actors from MapA on your GameInstance, unloading MapA (which destroys all its actors and invalidates those references), and then loading MapB and trying to access MapA actors through GameInstance. Instead of saving references to the objects themselves try saving an identifier of the object (such as a string or int ID) which will survive level transitions without being destroyed.

Currently having this issue where I need to pass over player stats upon new level loads to keep track of the players data. It works fine for the player, but now Im trying to make it keep track of certain actors, like doors, gates, and npcs. For example I want it to kill any actors listed in an array called “killedAI” which they all add themselves to upon death. I set up messages to print on string in case of failure to cast, but instead the event never fires from game instance at all. Can the game instance not access actors directly in the level?

Each of these actor types casts a variable to the game instance when interacted with, so they should be in the array or the map when the player dies and the map reloads. I’ve tried adding in delays thinking maybe too much was happening at once. Not sure what to do.

Can you possibly make an example of this? Having trouble visualizing how to accomplish it in blueprint.

Can you explain to me more about what you’re trying to do and why you need to keep a reference to some actors after their containing level is unloaded/destroyed? Is the new level that’s loaded the same level as the one that was unloaded (i.e you’re just restarting the same level)? What I meant is that actor references will become invalidated so you need a different approach, but that depends on what you are trying to accomplish.

When the character dies, it passes over his equipment and current inventory. When he dies and respawns it restarts the levelI need it to check for items he’s picked up, gates he’s opened, and doors he’s unlocked so he can’t collect the items again or get trapped in the map cause a door he unlocked is now locked. Mainly I just need it to check for the actors on level start after the levels been re opened.

Ok, I think I understand. At some point you might need a more complete saving/serialization implementation, but here’s a quick and simple solution that I tested. I uploaded the sample code [here][1] for reference.

Going back to the main issue, the problem is that we cannot save a list of actor references as these will be invalidated when the level is unloaded and will no longer point to anything. If we had a value such as a string or integer that uniquely identifies an actor then we can save it in our GameInstance and it won’t be invalidated. It turns out that [UKismetSystemLibrary::GetObjectName][2] can give us that (see [here][3] for more info), so let’s use ObjectName as a way to uniquely identify an actor.

Going with the example of saving a list of doors that have been opened, we’ll create a variable in our GameInstance called UnlockedDoorNames which is a string array of the names of opened doors.

Then in our door blueprint we let each door add itself to this array when it’s unlocked by the player, similar to what you’re doing in your code:

So now we have a unique reference to all the open doors which will persist after a level load/unload, but it’s not a reference to the actor itself, and we can’t do much with it. To find the actual actor using its ObjectName we would need to iterate through all actors in the level comparing their ObjectName until we get a match, which is too expensive. So instead let’s do a few things:

1- Create a tag which we will use in the editor to mark every actor that needs to be referenceable across different levels. Let’s call this tag Referenceable and tag our BP_Door with it. Using a tag makes it easy to batch edit multiple actors and tag them at once (using the property matrix editor).

2- Create a new variable in GameInstance called ActorReferences, which is a map of type String (ObjectName) → Actor Reference

296143-annotation-2020-02-01-174327.png

3- Create a helper function on GameInstance called PopulateActorReferences. This looks for all actors with the Referencable tag in the current world and adds an entry in the ActorReferences map linking the ObjectName with a reference to the actor.

Now we just need to call this function once at BeginPlay and we have a reference to every Referenceable actor through its ObjectName, which means using our UnlockedDoorNames array we can actually retrieve the list of opened door actors like so:

Now we finally have a reference to each door actor and we can do anything we want with it.

Hope this helps. The sample code looks a bit different as it’s more robust but the idea is the same.

Here’s what it looks like

Thank you it worked perfectly.

Glad it worked!