-
Notifications
You must be signed in to change notification settings - Fork 124
Continuous Running No Timers Needed
A programmable block can be configured to run itself in given intervals without the use of a timer block; either every tick, every 10 ticks or every 100 ticks. This means that there's no need for a timer block in order to run a script continuously. The trick to this lies in the Runtime.UpdateFrequency
property.
-
UpdateFrequency.Once
: The programmable block is automatically run once next frame and then not again or until you setRuntime.UpdateFrequency
again. -
UpdateFrequency.Update1
: The programmable block is automatically run every single tick. You should be careful about using this option unless your script is well written, as it might affect game performance. -
UpdateFrequency.Update10
: The programmable block is automatically run every 10 ticks. -
UpdateFrequency.Update100
: The programmable block is automatically run every 100 ticks. -
UpdateFrequency.None
: The default value. No automatic repetition, just a single run like normal.
It is recommended that you set this property in the programmable block's constructor, but you are free to alter this flag whenever you need to.
This property is a flag, which means you can combine more than one value in a bitwise manner. You can read more about enumeration types as bit flags here, about halfway down the page.
public Program()
{
// Configure this program to run the Main method every 100 update ticks
Runtime.UpdateFrequency = UpdateFrequency.Update100;
}
You can also request multiple frequencies.
public Program()
{
// Configure this program to run both Once and every 100 update ticks
Runtime.UpdateFrequency = UpdateFrequency.Once | UpdateFrequency.Update100;
}
Due to how the game engine works, and how the game needs to attempt to schedule out script executions to avoid performance hits, setting these flags does not guarantee that the given number of ticks are skipped before the next time your script is called. This means that you should consider the flag a polite suggestion more than an order. In a worst case scenario, rare but quite possible, the interval could become near-double of your request. The exceptions are UpdateFrequency.Update1
and UpdateFrequency.Once
, they are pretty much guaranteed.
Of course, there are many ways to run a script. It can be run from a button, a timer, a sensor... and much more. For this reason it's important to know how your Main function was called, so you can act accordingly. This is where the Main function's updateType
argument comes into play.
public void Main(string argument, UpdateType updateType)
-
UpdateType.Trigger
: Called from a button, timer, sensor or other simple trigger. An argument will be passed with this flag. -
UpdateType.Script
: Called from another programmable block. An argument will be passed with this flag. -
UpdateType.Terminal
: Called manually through the Terminal. An argument will be passed with this flag. -
UpdateType.Mod
: Called from a mod. An argument will be passed with this flag. -
UpdateType.IGC
: A message has been received through the communications system. The argument will be the callback identifier for the transmission channel. -
UpdateType.Once
: Called automatically by the programmable block because theRuntime.UpdateFrequency
was set toUpdateFrequency.Once
. This flag does not support arguments (but arguments might be passed if another flag is set) -
UpdateType.Update1
:Called automatically by the programmable block because the
Runtime.UpdateFrequency
was set toUpdateFrequency.Update1
. This flag does not support arguments (but arguments might be passed if another flag is set) -
UpdateType.Update10
: Called automatically by the programmable block because theRuntime.UpdateFrequency
was set toUpdateFrequency.Update10
. This flag does not support arguments (but arguments might be passed if another flag is set) -
UpdateType.Update100
: Called automatically by the programmable block because theRuntime.UpdateFrequency
was set toUpdateFrequency.Update100
. This flag does not support arguments (but arguments might be passed if another flag is set)
Important consideration: The same way you can set multiple Runtime.UpdateFrequency
flags, More than one of the flags may be set at any one time. For example, if you have enabled both Update1
and Update100
, and they both happen to hit the same tick, UpdateType
will have both these values. The consequence of this is that we cannot use a simple switch
to detect our sources. Instead, what we need to do, is to check if any given flag is set before running our logic related to that source.
public void Main(string argument, UpdateType updateType)
{
// If the update source is from a trigger or a terminal,
// this is an interactive command.
if ((updateType & (UpdateType.Trigger | UpdateType.Terminal)) != 0)
{
RunCommand(argument);
}
// If the update source has this update flag, it means
// that it's run from the frequency system, and we should
// update our continuous logic.
if ((updateType & UpdateType.Update10) != 0) {
RunContinuousLogic();
}
}
void RunCommand(string argument)
{
// Perform interactive logic
}
void RunContinuousLogic()
{
// Perform continuous logic, like monitoring, LCD updates and similar
}
An alternative way to check for more than one flag at once:
const UpdateType CommandUpdate = UpdateType.Trigger | UpdateType.Terminal;
public void Main(string argument, UpdateType updateType)
{
// If the update source is either Trigger or Terminal, run the interactive logic
if ((updateType & CommandUpdate) != 0)
{
RunCommand(argument);
}
}
void RunCommand(string argument)
{
// Perform interactive logic
}
Yeah, well, some people just have trouble grasping the bitwise operations, there's nothing wrong with that. So let's try to simplify this a bit.
Consider this part:
if ((updateType & ()) != 0)
{
// The code you want to run when the given update types are called should be placed here
}
Simply see this as mandatory code, you don't really need to understand it, but you need to keep it around. Combine every flag you want this conditional to trigger for, separate them with a |
symbol. So if you want code to trigger when either the per-tick or per-100-tick automatic update is configured, you put those flags together like this UpdateType.Update1 | UpdateType.Update100
and simply plug them into the ()
part in the code above, so it looks like this:
if ((updateType & (UpdateType.Update1 | UpdateType.Update100)) != 0)
{
// The code you want to run when the given update types are called should be placed here
}
Your conditional code will now run whenever the desired flags are set. That's really all you need to understand.
You do have the option of using the updateType.HasFlag
method, but this has a significant performance impact and is not recommended.
Do you have questions, comments, suggestions for improvements? Is there something I can do better? Did I make a mistake? Please add an issue here, and prefix your issue title with Wiki. Thank you, your help will be very appreciated!