How to avoid race conditions on concurrent events (using Blueprints)

Hey guys, I am in my first week of learning the Unreal Engine and so far I am working only with the editor and with blueprints, so I’m not coding anything (I have decent programming experience, but only in Java)

I have a player (Pawn blueprint, since I don’t actually need a Character) which has a “energy” variable. The energy is regenerating automatically over time. I am doing this in the “Event Tick” node of my player, because I want to have a steady regeneration rate independent of the framerate. The logic in the Event Tick node is basically:

if (at least X ticks passed since last energy regeneration) 
 -> get current energy value
 -> calculate energy += 1% 
 -> set new energy value

There’s also an event in my game where I want to set the player’s energy to 0. For test purposes I just trigger this on a key press. So I have a “Enhanced Input Action” node where I have the logic:

Set health = 0

Now from my general programming knowledge, I guess there’s already potential race conditions here, because the “Event Tick” node and the input action node could be executed concurrently, I assume?

Meaning that we can have this sequence in logic:

[Logic in event tick node]
get current energy value, e.g. 60% right now
calculate energy += 1% = 61%
[Now the logic from the triggered input action node interferes: set energy = 0%]
[Logic continues in event tick node]
set new energy value = 61% because this was already calulated before

So the event that was supposed to set the energy to 0 would get overwritten, and the energy would immediately go back from 0% to 61%, instead of starting again at 1%.

Now I know in “real programming” you would have to synchronize access to shared variables, so my question is: Can I do this without C++ code in the Blueprints? Are there thread-safe variables, or some other means of synchronizing such access?

I tried to define my own function in a separate “Energy Manager” Actor Blueprint which holds the energy variable, and has a boolean to lock concurrent access. But this is not the locking you usually would have, where a process would wait until the resource is free. With my solution I can only have a branch on the boolean and if it’s false I can just ignore the event. But this means I couldn’T process multiple events when they appear concurrently. I then thought of just collecting all incoming changes to the energy value in some queue and process them one after another. But again here I would need a thread-safe queue, right?

Right now I hit a dead end pretty much. I wouldn’t know how to program a functioning game when I cannot prevent such race conditions.

Thank you very much!

1 Like

Bumping this - I’m a bit surprised that noone answered yet, since this is about a very generic problem, and even my example is a scenario that should exist in pretty much every game in some way or another. At the moment I wonder how anyone gets any kind of working logic in their games :sweat_smile: So there must be something basic that I don’t know/understand yet about the Engine. Can someone please help out a noobie so that I know how I can continue with my game. Thanks :pray:

1 Like

This was… a lot.

Also, HELLO.

Yes, you can have concurrent processes with Blueprints!

You can create CUSTOM_EVENTs, utilize SEQUENCES, as well as built-in functionality of some nodes to handle their own function while the execution pulse continues firing.

If you want to get comfortable with Blueprints, I suggest UnrealSensei’s beginner course.

It’s free.

You can jump back and forth for what you need through the timeline, but he does, in those five hours, crash course you into making a simple game sequence.

(PS: I learned C++ first, but because I am not interested in physics AT ALL, Blueprints are much more efficient, for me. But if you are interested in physics, then C++ is the way to go.)

Can you show you BP? IMO you probably are using a copy of the value or its not being set properly.

@Leo HI! Thanks for the tip about the course, I’ll check it out!

@pezott1
Here’s the logic from my player BP where I regenerate energy over time - this is part of a “sequence” where other stuff happens before, but it branches off from the “Event Tick” node. As you can see I basically “Get” and “Set” the energy variable that is defined in the player BP (the exact calculations shouldn’t matter to you I guess)

And then I have this other simple event in the player BP that triggers on a button press and that sets the energy straight to 0:

image

So again, my question is if this is already a problem where the energy = 0 from the action input might get immediately overwritten by the logic in the event tick? The chanes of a race condition - if both events can be processed concurrently - are quite high I guess, since the event tick basically happens all the time.

And if there is the potential for such race conditions between event nodes, does it means that variables should always be processed only in a single event node, and shouldn’t be used in different events (at least for write operations)? So in this case here, I just have the idea that in the action event node, I could just set some boolean variable that signals that the energy should be set to 0, and do the actual writing to the variable also in the “Event Tick”…

Would this be the general approach then how to work with “shared” variables accross different events?

Thank you guys :hugs:

This simply doesn’t happen. Each event and sequence of nodes is executed in order, so you won’t have an event or node run in the middle of another. The only question here is if the input is executed before tick in the same frame, and this is unrelated to the issue.

Some suggestion to help find the issue:

  • Try adding a print node in the input event to be sure its working.
  • Add print nodes before the first branch with the value of Energy and another after you set the new value to manually check the conditions.
  • Right click on Energy variable and find all references to be sure it’s not being used some other place.
1 Like

Yes, keeping the logic in just one place is more practical

Its your first week.
And you are starting off the wrong foot…

Tick is frame dependent - surprised no one said this in here since they all know this…

To have it frame independent you’d have to use a timeline function or make use of the delta time off the ticknode (turns out you did) - but its till linked to each frame.

Yes, you can alter the tick rate - but it still doesnt really do what you want; your code will only add energy when it ticks.

The whole point should be that running the thing off a potato with 1fps a minute doesn’t cause your battery to reach a charge in a minute when the next tick occurs…

For that, it’s really easiest to add a timeline, start it off, and maybe keep it looping - depends on logic.

Regarding concurrent execution - there’s no chance. The system thread will not allow X to run while B is running or viceversa.

The only way to achieve that is custom Async threading. Wouldn’t worry about it until after using the engine for over a year.

You’d think “but 2 actors, same tick interval, the tick is concurrent”. Really its not.
The system thread will stack them in the order the actors have been loaded, and they’ll fire off consecutively.

Re the rest, since its your first week… lets learn about By Reference :wink:
It should address/do what you want with minimal thinkering.

This is called a Stack.
Look up Malloc stack, since its the very basics of all programming and the core concept behind almost abytning C/C#/C++ or hec, lets just say all OOP…

Regarding your specific issue of the value not getting to 0…
Your math is the issue.
And the use of floor.

Debug it - As suggested - using print strings.

Also add breakpoints and verify what is hit/when, and what the values are.

Also, what is actually happening In Practice?

Because this sounds more like conjecture than an “i have an actual problem where I know the value isnt being set”…

1 Like

Regarding concurrent execution - there’s no chance. The system thread will not allow X to run while B is running or viceversa.

Ok, this is good to know, thanks. So it means there shouldn’t be a problem with how my payer blueprint is modeled right now.

But is this sequential execution of nodes the case just on a per-blueprint basis, or in the entire game across all actors and nodes?

Because this sounds more like conjecture than an “i have an actual problem where I know the value isnt being set”…

I did have an actual problem but now I understand it better. What I did is I wanted to have the energy adjust over time to have a smooth animation of my energy bar filling/depleting, and I used a timeline in another BP/event. And that’s when the energy values got messed up. I guess to achieve this animation I must not directly use the energy variable from the player for my UI, but have separate variables there that the timeline is modifying.

But when this happened I wasn’t sure if it’s also a problem in my player BP and whether in general I could have this issue of race conditions. But now I understand it better.

Thank you!

You can directly set the energy to what you want and Interpolate the values just in the UI to achieve smooth animation.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.