Jump to content
Unity Insider Forum

Scripten in Unity für Nicht-mehr-Einsteiger


Sascha

Recommended Posts

Wer sich das Tutorial für Einsteiger in aller Gemütlichkeit durch gelesen hat, wird jetzt vermutlich etwas ordentliches scripten wollen.

Also machen wir uns mal an die etwas fortschrittlicheren Sachen ran.

 

Scripten in Unity für Nicht-mehr-Einsteiger

 

Teil 1 - Kommentare

Das ist eigentlich fast schon eine Nebensache, da sie für das Programm keine Relevanz haben: Kommentare.

Sie sind dazu da, um den Überblick zu behalten, oder auch, um anderen etwas zu verdeutlichen.

Es gibt zwei Sorten von Kommentaren: Einzeilige und Blockkommentare.

Einzeilig:

//Alles was hinter den beiden Schrägstrichen steht, ist ein Kommentar und wird vom Programm nicht beachtet

Block:

/*
Hiermit gehen auch
mehrzeilige Kommentare
*/

Kommentare werden von ordentlichen Editoren (und der Unity-Scripteditor gehört dazu) farblich abgesondert; praktisch.

 

Kommentare haben einen weiteren Nutzen: Man kann Programmteile "auskommentieren".

Setzt man vor eine Anweisung die beiden // , dann wird sie natürlich nicht mehr ausgeführt.

So kann man, falls man will, das Script testen, wie es ohne läuft.

 

Teil 2 - Die If-Abfrage

Eine Funktion löst eine andere aus - das ist ja schon ganz nett.

Aber will man ein Spiel schreiben, reicht das noch lange nicht aus.

Es gibt ein paar Strukturen in der Programmierung, die sollte jeder kennen.

Da wäre zum ersten die If-Abfrage.

"if" bedeutet auf deutsch "falls".

 

Die If-Abfrage besteht aus einem Kopf, in dem eine Bedingung steht - diese ist eine Variable vom Typ boolean (erinnere: ja oder nein) - und einem Körper, in dem wie bei der Funktion Anweisungen stehen.

if(bedingung)
{

}

Sollte die Bedingung den Wert "true", also "ja", haben, dann werden die Funktionen im Körper, also zwischen den geschweiften Klammern, ausgeführt, sonst nicht.

Beispiel:

if(true)
{
print("Ich scripte hier!");
}
if(false)
{
print("Ich scripte nicht.");
}

Sollte in dem Körper der Abfrage nur eine einzige Anweisung stehen, darf man die geschweiften Klammern weg lassen.

Ein weiteres Besipiel:

var klappt : boolean = true;
function Start()
{
if(klappt)
 print("Es klappt.");
klappt = false;
if(klappt)
 print("Wenn das klappt, fress ich einen Besen.");
}

Du bemerkst vielleicht, dass ich die Zeilen einrücke.

Das macht man für gewöhnlich mit Tab (Die Taste links neben Deinem Q), das klappt aber nicht so gut in Foren, daher hier nur Leerzeichen.

Der Sinn dahinter ist, dass man auch bei komplexeren Strukturen nicht den Überblick verliert, welche Anweisung in welcher Abfrage steht.

Da hat jeder so seine eigene Methode, ich zum Besipiel setze die öffnende geschweifte Klammer immer unter den Funktions- / Abfragen-Kopf, die meisten setzen sie dahinter.

Hauptsache ist, man selbst hat noch den Überblick, optimalerweise auch andere, falls man mal anderen etwas zeigen will.

 

Nun aber weiter im Text: In If-Abfragen kann man auch andere Variablen benutzen als boolean.

Dafür muss man den Wert mit einem anderen vergleichen.

Dabei kommt dann heraus: "Ist gleich" oder "ist ungleich", und das ist dann wieder unser benötigter boolean-Wert.

Zum Vergleichen benutzt man ein doppeltes Gleichzeichen ( == ), denn das einfache ist ja schon für die Wertzuweisung zuständig.

Beispiel:

if(3 == 4)
print("Diese Anweisung wird nicht ausgeführt werden.");

var hi : String = "Hallo";
if(hi == "Hallo")
print("Diese Anweisung wird ausgeführt.");
// Achtung: String-Vergleiche funktionieren nicht immer so einfach, in diesem Fall geht's

Für mathematische Vergleiche gibt es auch andere Operatoren als das == .

Zum Beispiel:

< kleiner als

> größer als

<= kleiner oder gleich

>= größer oder gleich

!= ungleich

 

Teil 3 - Logische Operatoren

Mehrere Bedingungen ( = boolean-Variablen) lassen sich zu einer zusammenfügen, indem man so genannte logische Operatoren verwendet.

So kann man im Script abfragen, ob zwei Bedingungen stimmen, oder nur eine von beiden.

Da wäre zum einen das logische Und ( && ).

if(4 > 3.5 && "wurst" != "käse")
print("Das hier wird ausgeführt");
if(4 > 3.5 && "wurst" == 5)
print("Das hier bestimmt nicht.");

Auf diese Weise lassen sich belieblig viele Bedingungen kombinieren.

So spart man sich das Stapeln von Abfragen:

if(4 > 3.5)
{
if("wurst" != "käse")
 print("Das hier würde genau so funktionieren wie das oben.");
}

 

Dann gibt es noch das logische Oder ( || ).

Einen | erzeugt man mit AltGr+< (die Taste neben der linken Umschalttaste).

Eine Oder-Bedingung gilt dann als wahr, wenn eine ihrer Teilbedingungen wahr sind:

var zahl : int = 4;
if(zahl == 2 || zahl == 4)
print("Das hier wird sowas von ausgeführt...");

 

Mehrere logische Operationen sollten unbedingt voneinander abgetrennt werden, das geschieht mit normalen Klammern ( ( und ) ):

if(("a" == "b" || 3 == 3) && 2 > 0)
print("Auch das hier wird ausgeführt.");

 

Teil 4 - Else

Jetzt kennst Du bereits if. Aber gibt noch mehr solcher Strukturen.

 

Da wäre zum einen else.

"else" heißt auf deutsch "sonst", und das passt.

Wer aufgepasst hat, kann sich die Funktion schon denken:

if(3 > 5)
print("Das wird nicht ausgeführt");
else
print("Das aber schon.")

auch else kann einen Körper mit geschweiften Klammern haben, damit es mehrere Anweisungen gibt:

if(false)
{
//...
}
else
{
//...
}

 

Teil 5 - While-Schleife

Jetzt kommt noch eine weitere Struktur. Sie ist der If-Abfrage sehr ähnlich, hat aber den Unterschied, dass die Anweisungen im Körper nicht nur ein Mal ausgeführt werden, wenn im Kopf "true" steht, sondern immer wieder ausgeführt werden, bis "false" im Kopf steht.

Das ist in den allermeisten Fällen nur sinnvoll, wenn der Wert, um den es im Kopf geht, im Körper geändert wird.

var zahl : int = 0;
while(zahl < 5)
{
print("Es wird getan!");
zahl = zahl + 1;
}

Am Ende haben wir hier fünf Mal den angegebenen Satz in der Konsole stehen.

Daran sieht man schon einmal den primären Nutzen von Schleifen: etwas soll x Mal ausgeführt werden.

Für diesen Zweck allerdings ist die For-Schleife nützlicher. Bevor die dran kommt, erst einmal neue Operatoren!

 

Teil 6 - Neue Operatoren

Es gibt ein paar nützliche Operatoren, die noch gar nicht dran kamen.

 

Da gibt es z.B. + als "Concat"-Operator, der Strings zusammenfügt:

var name : String = "Hase";
print("Mein Name ist "+name+".");

Wer errät's? Am Ende steht da "Mein Name ist Hase."

Sehr wichtig!

 

Das funktioniert auch mit Strings und Zahlen:

var zahl : int = 3;
print("Die Nummer lautet "+zahl);

Aber Vorsicht bei Rechnungen in diesem Falle, benutze Klammern!

print("Drei plus zwei ist "+(3+2));

...denn das + ist immernoch auch zum Rechnen da.

 

Jetzt gibt es noch schnelle Rechenoperatoren:

zahl++;

Erhöht "zahl" um 1, genau wie

zahl--;

..."zahl" um 1 verringert.

Dann gibt es noch diese:

zahl += 5; //entspricht zahl = zahl + 5;
zahl -= 5; //entspricht zahl = zahl - 5;
zahl *= 5; //entspricht zahl = zahl * 5;
zahl /= 5; //entspricht zahl = zahl / 5;

...für schnelleres Rechnen. Yay!

 

Dann gibt es noch das Ausrufezeichen ( ! ).

Dieses kann man benutzen, um boolean-Werte umzukehren.

Dieser Code:

if(lebtNoch == false)

...entspricht diesem:

if(!lebtNoch)

Das ist nicht notwendig, aber ganz schön praktisch!

 

Teil 7 - Die For-Schleife

Mit der For-Schleife geht Zählen besser als je zuvor!

Anstatt sie aber im Detail zu erläutern, werde ich jetzt erstmal einfach die gängigste Verwendungsweise vorstellen:

var wieOft : int = 5;
for(var i : int = 0; i < wieOft; i++)
{
print("Wir sind bei "+i);
}

Der Kopf der For-Schleife besteht aus drei Teilen, die per Semikolon ( ; ) voneinander getrennt sind.

Der erste Teil ist eine Anweisung, die am Anfang der Schleife ausgeführt wird (hier kann man eine Variable deklarieren und initialisieren!),

der zweite Teil ist eine Bedingung, die vor jedem Durchlauf der Schleife abgefragt wird (genau wie in der While-Schleife, bei false wird die Schleife abgebrochen),

der dritte Teil ist wieder eine Anweisung, die nach jedem Durchlauf ausgeführt wird.

 

Dieser Code ist also von der Funktion her identisch mit diesem:

var wieOft : int = 5;
var i : int = 0;
while(i < wieOft)
{
print("Wir sind bei "+i);
i++;
}

...und ist dabei wesentlich sauberer und schicker.

 

Teil 8 - Return und Break

Return wurde im vorherigen Tutorial benutzt; mit return lassen sich Werte von einer Funktion zurück geben.

Wer sich nicht erinnert: Die Funktion wird dadurch beendet.

Man kann return auch ohne Wert benutzen:

return;

...einfach, um die Funktion zu beenden.

Das hat einen ganz einfachen nutzen: Man spart sich jede Menge geschweifter Klammern.

Denn anstatt einen riesigen Anweisungsblock einer Funktion komplett in eine If-Anweisung zu packen (man denke nur ans nachträgliche Einrücken...), kann man einfach die Funktion am Anfang mit diesem Code versehen:

if(!wirdGemacht)
return;
//...

 

Break ist ein Befehl, der ähnlich wie return verwendet wird, er beendet aber nicht die Funktion, sondern die Schleife, in der er steht.

Logischerweise gibt's hier keinen Rückgabewert, Schleifen haben ja keinen.

while(zahl < 5)
{
if(zahl == 4) //Ich würd gerne vorher abbrechen...
 break;
print("Wetten, das hier wird nicht ausgeführt, wenn zahl gleich 4 ist?");
}

Dieser Code macht nicht viel Sinn, aber break kann durchaus von großem Nutzen sein.

 

Teil 9 - Switch-Case-Abfrage

Eine interessante Abfrage gibt es noch:

Man stelle sich vor, man hat eine Zahl, und abhängig von dieser möchte man etwas tun.

Eine KI zum Beispiel hat eine Variable "modus".

Ist modus 1, so steht sie herum, bei 2 sucht sie den Spieler, bei 3 schießt sie wild umher und bei 4 tanzt sie Disco Fox.

Will man das Verhalten nun abhängig vom Modus gestalten, bietet sich theoretisch eine Reihe von If-Abfragen an:

if(mode == 1)
Idle();
else if(mode == 2)
Search(player);
//usw.

Das ist etwas unschön und verstößt auch gegen einige Regeln für sauberes Programmieren.

Ändert man nämlich den Namen der Variable, schaut man doof aus der Wäsche.

Deshalb schafft switch-case Abhilfe.

Der Code oben lässt sich in einer Case-Abfrage so ausdrücken:

switch(mode)
{
case 1:
 Idle();
break;
case 2:
 Search(player);
break;
//usw.
}

Das break ist wichtig, weil die Engine ohne das Schlüsselwort auch bei einer Übereinstimmung den Switch-Block weiter abarbeitet.

Sollte in einem Case-Block "return" mit Sicherheit aufgerufen werden, darf man sich das break natürlich sparen.

Ein Schlüsselwort gibt es noch: default.

switch(mode)
{
default:
 //...
break;
}

Der Code in einem default-Block wird immer ausgeführt und kommt daher z.B. an die Reihe, wenn mode aus irgendeinem Grund -1 ist.

Er kommt nach allen case-Blöcken vor Ende des Switch-Blocks.

Er sollte samt break immer vorhanden sein, auch wenn kein Code darin steht, sonst gibt es ja kein break!

 

Teil 10 - Abschließende Worte

All das hat in Unity überhaupt keinen direkten Nutzen gehabt.

Wir haben ja nicht einmal ein neues Script geschrieben.

Aber sicherlich kannst Du Dir denken, dass man ohne Abfragen und Schleifen nicht weit kommt.

 

Und ich glaube, der passende Artikel für Script ist "das".

Ich kann es mir trotzdem nicht angewöhnen.

 

Viel Spaß beim Scripten!

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 3 weeks later...
  • 1 year later...
  • 3 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Lädt...
×
×
  • Neu erstellen...