Casting an integer variable - only casts a default value for some reason

Hey everyone, I have a question, probably simple, but I can’t seem to solve it…

I’m trying to cast a variable from one blueprint to another. Basically, that variable represents the “Current Round.” It is an integer w/ a default value of 1. Every time I go to the next round, that value changes and gets added to by one. This part works well, as evidenced by the fact that I have another integer variable that multiples it by 2 to increase the Target Goal with each new round. It happens in the same blueprint and it works well.

However, I’m trying to cast this “Current Round” variable to another blueprint to affect how fast the enemies get spawned, using the “Cast To” node. Then, that other blueprint will use the Branch node to determine whether the Current Round is above the certain number and increase the spawn time.

However, only the Default value of 1 gets casted for some reason! I don’t need the default value, but the final end value of the variable :(. In this case, the actual number of the Current Round.

Looking forward to any suggestions, thank you.
UE5.0.1

Hi, could you share a screenshot of the blueprint code, don’t really get why you need to cast an integer. Do you always set the value after adding 1 to it? If you use increment you don’t need to do it but otherwise always. Hope that helps.

SevenOperation, thank you for your response. Yes, I’m using increments. I will go ahead and post a snapshot of the codes as soon as I have a chance (I’m working for the next few days). I didn’t post them at first because I thought it was just a simple generic answer…

Here is a screenshot of the code:

The cast goes through. But when I debug it, I can see that it is based on the initial value of the “Current Round” variable, as was set in the other blueprint, not the actual round of the game (1,2,3,4,5, etc).

Here is the blueprint that makes the “Current Round” reflect the actual round of the game.

There is a lot more to what makes the “Current Round” reflect the actual round of the game (I don’t want to post a bunch more blueprints since it would be too complicated) but the fact is - it works, I know that for various reasons. Here is one example. Every new round, I multiply the “Current Round” variable by 2, which is the Target Goal. I display that number on the HUD whenever the new round starts, and it works:

Every time I kill all the enemies and go to the next round, the Target Goal goes up (2,4,6,8…).

Here is another example. I display the “Current Round” on the transitional menu between rounds. In this case, the Cast To works perfect, and casts not the default value of 1 every time, but the actual round of the game:

But then why does it only cast the default value in that first blueprint where I try to affect the enemy spawn time?

Even with the code its difficult to help. One thing that comes to my mind is, if you are respawning the player in any way, that would loose the value. Another idea that would be a bit more in line how its supposed to be, you could move the current round variable to the GameState object, which you can access anywhere.

1 Like

@GeneG90 hmm yeah seems odd but thanks for the screenshots will try to replicate it :slight_smile:
Also just out of curiosity in the second screenshot isn’t that the player controller? because if so you don’t have to get it with the GetPlayerController function and instead just use this or something :slight_smile:

I will try to replicate the issue and will let you know if I find a solution or at least the reason for this behaviour.

Hmm ok, I looked a little bit closer at the screenshots and I need you to clarify some stuff for me :slight_smile:
The first screenshot is where the error happens right? If you would switch the level by respawning the player/loading another level the controller would be reset to the default value so the counter would be 0 again and since you load the value directly on Begin Play I think you have a neat little race condition. I would suggest you save the number in the game state as @dowhilefor suggested then your problems should be gone or you would pass the number into the level. You could also of course write it into a file and so on.

Would be great to see a screenshot of the Save Round function of screenshot too. Since it would seem to me that you kind of already set it somewhere outside maybe already into the game state or a file? if so just use the same logic in the “Event begin play” to get the number as you use for your game controller.

Hopes that helps

Your Cast - use “Get player pawn” instead

1 Like

Thank you for the suggestion. If you’re willing to look closer into it, let me give you some more details as to what makes the “Current Round” work.

And I understand that you’re going above and beyond, so there is absolutely no pressure for you to study through all of it. This game is just for the learning purposes, where I’ve been guided to create this code, and eventually I’ll figure it out on some other learning experience.

So, I actually use the “SaveGame” Blueprint Class to store the value of the “Current Round” before adding 1 to it. That is pretty much what the new level is - the only thing that is changed is the value of the “Current Round.” I then either multiply it by two to get my enemy “Target Goal,” or in this case trying to set up a Branch node so that when the “Current Round” reaches a certain value - the Spawn time changes.

The “SaveGame” blueprint class stores one variable - “Round.” When I load the level, I pull the value of “Round” from SaveGame Blueprint into the “Current Round” variable. When I save it though, I do vice versa - I add 1 to “Current Round,” and then set the “Round” with the “Current Round.” Phew, hoping I’m making it clear…

Here are the screen shots. First is The EventBeginPlay of my main FirstPersonCharacter:

Here is that “Load Round” macro:

To summarize the above code - if you’re just starting the game with the first round, there are no saved games, so it goes through the “false” branch and leaves the “Current Round” at default value of 1. If there is a already a saved game present (I’m on level 2 or above), then it loads the game from the slot, and creates a value for my “Current Round” using the “Round” variable from the SaveGame.

Now, the question is, how does the “Round” variable of the “SaveGame” Blueprint get its value to begin with? The answer - with this “SaveRound” macro that you’ve asked about:

Untitled2

Basically, I add 1 to the current value of “Current Round,” and then save that value into the “Round” variable of the “SaveGame” blueprint. Only to pull it again later when the new level starts.

And it works. Thats how I’m able to increase the Target Goal with each new level, and display the Current Round on the transition screen between levels.

And the problem remains :frowning:

Your SaveGame is done a bit wacky way

So here’s a typical setup - you do it once when the Game starts, not by any save/load attempt, you only SaveGame to Slot later when you change variables

Another thing - don’t use SaveGame for this purpose
If you need variables to exist only from beginning of game till end and it doesn’t matter after you re-open the game (and it is so because every time you start a new game or re-open your Game you start from Level 1) - Use Game Instance to store this value as it is persistent, here’s a most known description of it:

GameInstance - Holds any non-pointer persistent variables (persistent means that you need to store in between two levels and that you don’t need to store in a SaveGame)

You can read and change the values there whenever you want and from every place

Also this:

Like mentioned above - you don’t need to reuse the nodes (from screenshot at the top of my Post)
Only save after changes, to get values simply get the Reference of your SaveGame Object

But enough complaining, let’s see what you can do about it

I display that number on the HUD whenever the new round starts, and it works

If it works for HUD - how do you apply it there to show up? It’s probably the same way you should go about your lil Variable

Also add some Print Strings (or use your HUD) to check values all the time and be aware if they do the right thing - that’s my personal experience as it’s pretty often that I think the math should do good, then it’s being affected by some other Factors and gets totally wrong at once

I assume you are using the Level Blueprint to control spawning the enemies
That means you probably need some Casts and those are very confusing sometimes

The most important thing in a Cast is the Object - you cannot Cast to Static Mesh Component while having your Player as Object because your Player isn’t a Static Mesh Component but an Actor or Pawn - keep that in mind

If you have only one player - Get Player Pawn → Cast To Player_BP_Name and so you can change things inside of it

If you wanna affect the Enemies - depends on how it works… if you wanna affect all actually spawned Enemies - Get All Actors of Class (no need to cast here because you select the Class)

If you wanna affect upcoming Enemies - you need to edit their information while Spawning them

So still in same spot where you check the actual Round - you also affect the Enemies Variables

Every Variable has 2 nice options - Expose on Spawn + Instance Editable - with this you will see the Variables when Spawning or Selecting the BP on Level and you can edit them immediately!

So back to the Level BP that spawns Enemies - when you have Exposed Variables - those will appear as part of Spawn Node and you can set the new Value based on the Round

If you wanna affect something that is on the Level placed manually - you can click it, got to Level BP and “Add reference to Selected Actor” - now you can edit the instance you referenced

I think this gets to long now, sorry for that but it’s not easy to pass knowledge and assist without an insight into your BP

Also it’s gonna be a lil challenge to you but that will give you the very valuable experience!

If there’s anything unclear, I am missing something or it’s not what you need - let me know, I’ll write you another book about it :smiley:

2 Likes

The best way to fix your issue is to do what @UnrealSolver said :slight_smile: would still think it is a race condition since you instantly try to get the current round from the player when begin play is called but the player (BP Fist Person Character) didn’t load the save game yet since when I am not wrong the Event Begin Play of the Character is called later. You could test it by setting breakpoints in both and see which gets triggered first :).

As a solution, if you for whatever reason like let’s say the player closes the game and starts it again, and should be in the same round you still want to use SaveGame just call Load Game from the slot where the error happens and get the round number that way.

A better way would be of course if it is just a number to just do this once inside the Game State and save the round there for as long as the game exists.

1 Like

Thank you, @SevenOperation! I considered the fact what you said about the “race condition,” and the fact that the EventBeginPlay of the FirstPersonCharacter might be called later. So I decided to go ahead and put a tiny delay after the EventBeginPlay of the blueprint where I spawn the enemies to give the other one a time to catch up. And it worked!

Thats me playing round 4 while I debug it.

Now, in personal humble opinion, if I ever make it to professional game development, I would consider such a move cheating, lol. Instead of figuring it out – WHY IS IT DOING IT?? Why is one EventBeginPlay starts before the other (one is in the Actor class and the other in a Character class) or if it starts simultaneously then what specifically in the blueprint that makes the progression to slow down? – I basically just slap a bandaid on it.

I’ve never had to work with Game State before, but it sounds like a more professional approach - to store the value in there and call it at the beginning of the game. I need to look into it.

@UnrealSolver, thanks for your response as well. I’ve read and reread it multiple times. I liked what you said about setting Print Strings to frequently check for the values. That would’ve been my next step, and I’ll use this approach in my other troubleshooting instances as well. Thanks for simplifying the SaveGame setup as well.

Glad you found your solution!

Yeah, that’s normal that some stuff starts before others and sometimes that leads to some data to not exist while we already try to reach it

PrintStrings are my good friend, although there are better ways of testing and debugging - for just logic cause within a small-mid project - I tend to place some print string here and there so I can be aware if the workflow or macros return values I need :slight_smile:

Now keep up the good work and make your Project to be the best one! :fire:

1 Like