Dauerbetrieb mit dem internen Timer

Kein Timer-Block mehr erforderlich


Ein programmierbarer Block kann so konfiguriert werden, das er in bestimmten Intervallen ohne Verwendung eines Timerblocks läuft: entweder jeden Tick, alle 10 Ticks oder alle 100 Ticks. Die dazu benötigte Eigenschaft lautet Runtime.UpdateFrequency.

  • UpdateFrequency.Once:
    Der programmierbare Block wird automatisch nur einmal im nächsten Frame ausgeführt. Danach musst Du Runtime.UpdateFrequency erneut einstellen.
  • UpdateFrequency.Update1:
    Der programmierbare Block wird automatisch bei jedem einzelnen Tick ausgeführt. Hier solltest Du unbedingt vorsichtig sein: Die Spielleistung kann bei unsauberen Skripten massiv beeinträchtigen werden.
  • UpdateFrequency.Update10:
    Der programmierbare Block wird automatisch alle 10 Ticks ausgeführt.
  • UpdateFrequency.Update100:
    Der programmierbare Block wird automatisch alle 100 Ticks ausgeführt.

Ich empfehle Dir diese Eigenschaft im Konstruktor des programmierbaren Blocks zu zu platzieren, aber Du kannst dieses Flag natürlich jederzeit im Code ändern. Diese Eigenschaft heißt "Flag", d.h. Du kannst mehr als einen Wert bitweise kombinieren. Mehr über Aufzählungstypen als Bit-Flags kannst Du weiter unten lesen.

public Program()
{
  // Konfiguriere dein Programm so, dass die Main-Methode alle 100 Ticks ausgeführt wird
  Runtime.UpdateFrequency = UpdateFrequency.Update100;
}

Du kannst auch mehrere Frequenzen einstellen:

public Program()
{
   // Konfiguriere dein Programm so, dass die Main-Methode einmal, und dann alle 100 Ticks ausgeführt wird
   Runtime.UpdateFrequency = UpdateFrequency.Once | UpdateFrequency.Update100
}

Vorsicht: 100 Ticks sind nicht immer 100 Ticks

Aufgrund der Funktionsweise der Spiele-Engine und der Art und Weise, wie das Spiel versuchen muss, Skript-Ausführungen zu planen, um Performance-Spitzen zu vermeiden, garantiert das Setzen dieser Flags nicht, dass die angegebene Anzahl von Ticks übersprungen wird, bevor das nächste Mal Ihr Skript aufgerufen wird. Das bedeutet, dass Sie dieses Flag eher als Vorschlag denn als strikte Anweisung dienen soll. Im schlimmsten Fall kann sich das Intervall nahezu verdoppeln. Die Ausnahmen sind UpdateFrequency.Update1 und UpdateFrequency.Once, die werden zu ziemlicher Sicherheit ausgeführt.


Der UpdateType

Natürlich gibt es viele Möglichkeiten, ein Skript auszuführen. Es kann über eine Taste, einen Timer, einen Sensor und vieles mehr gestartet werden. Aus diesem Grund ist es wichtig zu wissen, wie Ihre Hauptfunktion aufgerufen wurde, damit Sie entsprechend handeln können. An dieser Stelle kommt das Argument updateType der Main-Funktion ins Spiel:

public void Main(string argument, UpdateType updateType) 
{

}
  • UpdateType.Trigger:
    Wird von einer Taste, einem Timer, einem Sensor oder einem anderen einfachen Auslöser aufgerufen. Mit diesem Flag wird ein Argument übergeben.
  • UpdateType.Antenna:
    Wird von einer Antenne angerufen. Mit diesem Flag wird ein Argument übergeben.
  • UpdateType.Script:
    Wird von einem anderen programmierbaren Satz aufgerufen. Mit diesem Flag wird ein Argument übergeben.
  • UpdateType.Terminal:
    Wird manuell über das Terminal aufgerufen. Mit diesem Flag wird ein Argument übergeben.
  • UpdateType.ModApi:
    Wird von einem Mod. aufgerufen. Mit diesem Flag wird ein Argument übergeben.
  • UpdateType.Once:
    Wird automatisch vom programmierbaren Block aufgerufen, da die Runtime.UpdateFrequency auf UpdateFrequency.Once gesetzt wurde. Dieses Flag unterstützt keine Argumente (aber Argumente können übergeben werden, wenn ein anderes Flag gesetzt ist).
  • UpdateType.Update1:
    Wird automatisch vom programmierbaren Block aufgerufen, da die Runtime.UpdateFrequency auf UpdateFrequency.Update1 gesetzt wurde. Dieses Flag unterstützt keine Argumente (aber Argumente können übergeben werden, wenn ein anderes Flag gesetzt ist).
  • UpdateType.Update10:
    Wird automatisch vom programmierbaren Block aufgerufen, da die Runtime.UpdateFrequency auf UpdateFrequency.Update10 gesetzt wurde. Dieses Flag unterstützt keine Argumente (aber Argumente können übergeben werden, wenn ein anderes Flag gesetzt ist).
  • UpdateType.Update100:
    Wird automatisch vom programmierbaren Block aufgerufen, da die Runtime.UpdateFrequency auf UpdateFrequency.Update100 gesetzt wurde. Dieses Flag unterstützt keine Argumente (aber Argumente können übergeben werden, wenn ein anderes Flag gesetzt ist).

Mehr als ein UpdateType pro Aufuf

So wie Du mehrere Runtime.UpdateFrequency-Flags setzen kannst, können auch mehrere der Flags gleichzeitig gesetzt werden. Wenn Du beispielsweise sowohl Update1 als auch Update100 aktiviert hast und beide den gleichen Tick treffen, hat UpdateType beide Werte. Die Folge ist, dass wir einen einfachen Schalter nicht mehr verwenden können, um unsere Trigger zu erkennen. Stattdessen müssen wir prüfen, ob ein bestimmtes Flag gesetzt ist, bevor wir mit dem Code für diesen Trigger ausführen.

public void Main(string argument, UpdateType updateType)
{
  // Wenn das Update von einem Sensor oder einem Terminal kommt
  if ((updateType & (UpdateType.Trigger | UpdateType.Terminal)) != 0)
  {
    BeliebigesKommando(argument);
  }
  
  // Wenn die Updatequelle ein Flag hat, bedeutet das, das es 
  // vom UpdateFrequency kommt und wir führen eine andere Methode aus
  if ((updateType & UpdateType.Update10) != 0) {
    WiederkehrendesKommando();
  }
}

void BeliebigesKommando(string argument)
{
  // Führe einmalige Logik aus
}

void WiederkehrendesKommando()
{
  // Führe eine wiederkehrende Logik aus, wie z.B. LCD-Updates, Monitoring etc
}

Alternativ kann man auch Flags zusammenfassen und auslagern, das macht den Code etwas übersichtlicher:

const UpdateType CommandUpdate = UpdateType.Trigger | UpdateType.Terminal;

public void Main(string argument, UpdateType updateType) 
{
  // Wenn die Update Quelle entweder ein Sensor oder ein terminal ist, führe die Methode EinKommando() aus
  if ((updateType & CommandUpdate) != 0) 
  {
    EinKommando(argument);
  }
}

void EinKommando(string argument)
{
  // Führe diese Logik aus 
}