Search This Blog

Friday, March 10, 2017

Wait Waits For No One (A few words about Construct 2 System Action wait)

Wait Waits For No One

(A few words about Construct 2 System Action wait)




If you have a System action “wait” set to wait for 3 seconds, it does not make the game wait for 3 seconds.  It only makes that event wait for 3 seconds.  In fact, it only makes that particular instance of that event wait for 3 seconds.  The rest of the game and its events go on their merry way as if nothing happened.  


In other words if you have an event with a set of actions like:
If condition is true:  
  1. do action a
  2. do action b
  3. do action c
  4. wait 2 seconds
  5. do action d
  6. do action e

It does actions a, b, and c immediately, then puts actions d and e on the shelf for 2 seconds while it keeps running the rest of the events and behaviors in the game.   The game might go on for many ticks before it picks up actions d and e.  Nothing else waits except those two actions in that one event.


In fact it will go on repeating that same event every tick for every object that can be checked for that condition.   For example you could open another door while the first one is closing and it will work just fine with one event thanks to the wait action.  One wait doesn’t care what the rest of the program is doing or even other instances of itself.


This is handy for something like a door or monster that might have a timed series of actions.. But only for that particular monster or door.  Technically for the group of objects that meet the criteria set up in the event’s condition.


But  use wait with caution.  It can cause some problems as your code gets more complex.


Say you want your boss monster to do a shimmy - shake dance.  You might have an event that looks like:


  1. Shimmy
  2. Wait for 1 second
  3. Shake
  4. Wait for 1 second
  5. Shimmy again, Shoot some bullets...
  6. Wait for 1 second
  7. Shoot a giant missle at you.

You will expect when this series of actions is called, your monster will, after a shimmy, wait, shake, wait, shimmy again wait, fire a giant missle at you.  Once the action is called, the monster will fire a missle at you after 3 seconds.


There’s one problem.  

Once that action is called, the monster WILL fire a missile at you in 3 seconds.  What if one second later, you kill the monster and it should be lying down dead?  That action is still “sitting on a shelf” from 2 seconds ago, waiting to perform it’s “shimmy again, shoot some bullets...” action and then fire a missle at you, has no way of knowing it’s supposed to be lying down because of some other unrelated events somewhere.   


It will fire the missile anyhow.


Wait creates an asynchronous action.  In computer science, this is related to the concept of a “promise.”   


A promise is different from a condition in that a condition says “If A is true…then I’ll do B”  while a promise says “when A is true, then I’ll do B.”  (If then) is checking if A is true right now, and if so it will do B right now.   A promise says as soon as A is true then I’ll do B.  


When you have a promise set up to happen later, There’s really no way to make it not happen without putting some kind of “unless” clause in the promised action.  Like so:

1 shimmy
2 wait for 2 seconds
3 if not dead
4 shake. Fire some bullets.
5 wait for 2 seconds
6 if not dead
` 7 shoot a giant missile at you


Every time you have a wait, you need to have a condition to make sure it’s still appropriate to perform that action.

So somewhere in that promise you better think of an “unless” if you can think of any times you don’t want B happening.

Wait can be a powerful tool, but it can create unexpected behaviors that are hard to debug. And if you try to do wait in a loop, forget about it. You probably don't want to do that. Instead use wait for signal and consider why you are trying to wait within a loop. There's another even bigger problem:
Since nobody but the actions in the particular call of that event following the wait are going to wait, that same event is going to be called again EVERY TICK. So you need another big "Unless" in there to make sure the monster isn't ALREADY doing this. I like to use a variable called "state" and give it easy to read values like so:
If monster state is not "ShimmyShaking" (and whatever) 1. set monster state to "ShimmyShaking" 2 shimmy
3 wait for 2 seconds
4 if not dead
5 shake. Fire some bullets.
6 wait for 2 seconds
7 if not dead
` 8 shoot a giant missile at you 9 set monster state to "DoingSomethingElse"
In fact those "if not dead" checks can probably also be checks for the "ShimmyShaking" state since if the monster were dead it's state would probably be something like "dead." Using the System.wait action is explained in depth in the manual section by that name on the Scirra website: https://www.scirra.com/tutorials/56/how-to-use-the-system-wait-action

No comments:

Post a Comment