r/Kos•
space_is_hard

RunMode Loop Tutorial: How to avoid LOCKs and WHEN triggers in your scripts

Tutorial

#RunMode Loop Tutorial

##What is it?

A RunMode loop is a method of performing a series of programming actions that doesn't rely on triggers or locks.

##Why should I care?

RunMode loops operate on a purely linear basis; That is, unlike with triggers or locks, they don't skip back in the code to perform a separate block of code.

##Why is that useful?

Linear scripts like the RunMode loop are easier to follow and easier to debug because each line is only ever performed after the line before it.

##Are there any disadvantages?

  • RunMode loops can appear more complicated than they really are at first glance.

  • The longer the loop, the longer it will take for the entire loop to cycle. If you're not careful, you can bog down a short section of code in the loop with a longer section.

  • Unlike triggers and locks, each section of code in a RunMode loop will happen exactly once per cycle of the main loop unless you specifically tell it otherwise. In contrast, triggers (and to a certain extent, locks) will be evaluated/executed at the beginning of every physics tick regardless of what the rest of the code is doing.

##What does a RunMode loop look like?

RunMode loops will have a top-level loop that the rest of the code runs inside. Inside of the main loop will be blocks of code that you either A) want to happen every cycle of the main loop for as long as the loop runs, or B) only want to happen when certain conditions are met. The latter type of blocks will be surrounded by an IF statement with those conditions evaluating as true. Here's a quick pseudo-code example:

UNTIL exitCondition {

    IF AAAA {

        //We only want to do "stuff" when condition AAAA is true
        DO stuff.

    } ELSE IF BBBB {

        //We only want to do "otherStuff" when condition BBBB is true. This will necessarily be exclusive from condition AAAA
        DO otherStuff.

    }.

    IF CCCC {

        //We only want to do "thisStuff" when condition CCCC is true. This can happen independently of AAAA or BBBB
        DO thisStuff.

    }.

    //This stuff will happen every cycle of the loop until the loop exits
    EVALUATE(moreStuff).
    DO thatStuff.

}.

You can easily follow which of the IF blocks will evaluate based on the situation. You can also see the flexibility in how we're able to determine which blocks of code we want to execute when.

##What does this have to do with "RunModes"?

See AAAA and BBBB in the previous example? If you use a single variable (we'll call it RunMode, but you can call it whatever you want) for both of those, but check it for different values in each block, we can have one block disable itself and simultaneously enable a different block. This gives us the ability to have sequential blocks of code that only execute when the previous block has finished. Here's an example that's modified from the previous example:

UNTIL RunMode = 0 {

    IF RunMode = 1 {

        //We're only going to do "stuff" once before moving on to the next block
        DO stuff.
        SET RunMode TO 2.

    } ELSE IF RunMode = 2 {

        //We want to continuously do "otherStuff" until condition AAAA is true
        DO otherStuff.

        IF AAAA {

            SET RunMode TO 3.

        }.

    } ELSE IF RunMode = 3 {

        //We also want to keep doing "thisStuff", but this time we'll do it until we're ready to exit the loop
        DO thisStuff.

        IF BBBB {

            SET RunMode TO 0.

        }.

    }.

    IF CCCC {

        EVALUATE(certainStuff).

    }.

    //This stuff will happen every cycle of the loop until the loop exits
    EVALUATE(moreStuff).
    DO thatStuff.

}.

##Protips

  • If you want to make your code even easier to follow, you can replace RunMode's integers with strings that briefly describe the block of code that they are intended to execute. However, this will remove the ability to do math on the RunMode variable, which can be useful in certain situations.

  • You can replace RunMode with core:part:tag or ship:rootpart:tag to allow the code to resume where it left off after a reboot. This works because, unlike the code itself, part tags persist through a scene change or reboot

  • Using WAIT or WAIT UNTIL will pause the entire loop, not just the section it's in. To continue evaluating the rest of the loop while having a certain block wait a set amount of time, you can do something like SET timer TO TIME:SECONDS and then have the next block execute IF TIME:SECONDS >= timer + X, where X is the number of seconds to wait.

Posted Jul 16, 2015, 3:09 AM UTC

1011
Loading comments…