Jump to content
Unity Insider Forum
Sign in to follow this  
Sascha

[C#] Wie deklariere ich meine Variable?

Recommended Posts

Hallo miteinander, wird mal wieder Zeit für ein neues Tutorial!

 

Macht doch einfach einen Extra Thread dafür auf, [...]

 

Das Thema heute:

Wie deklariere ich meine Variable?

 

Wer noch nicht so viel programmiert hat, hört manchmal in einem Tutorial von einer Lösung für sein Problem, versteht diese nicht ganz, probiert es aus und: Tadaa! Es funktioniert.

Ähnlich wie bei php gibt es aber auch für Unity eine Menge motivierter Menschen, die freundlicherweise nach ihren ersten eigenen Erfolgen gleich mit anderen Teilen, wie sie es geschafft haben.

Entsprechend wird das "warum" oft nicht weitergegeben, oder noch schlimmer: Es ist nur gefährliches Halbwissen. Dann bekommt man das nächste Problem, findet keine Lösung und besucht z.B. dieses Forum. Und da kommt's: Wie, deine Variable ist static?? Das ist ja großer Humbug!

Heute will ich möglichst knapp ein paar wichtige Modifikatoren auflisten, die Variablen in C# haben können.

 

Kleine Anmerkung: Dieses Tutorial wird alles andere als umfassend, da es für (Fast-noch-)Anfänger gedacht ist.

Außerdem: Es geht um Objekt- und Klassenvariablen, also nicht die Variablen, die man in einer Methode definiert.

 

Zuerst einmal werde ich auf allgemeines Programmieren eingehen. Die Bedeutung dieser Begriffe ist in C# immer so, wird aber in Unity erweitert.

 

C# allgemein

 

Variablentyp und Name

Darf bei keiner Variable fehlen: Der Variablentyp und der Name. Dahinter ein Semikolon.

typ name;

Der Typ gibt an, welche Werte die Variable haben kann: Gibt man z.B. int (also Ganzzahl) an, dann sind mögliche Werte 0, -4, 20 usw.

Der Name wird benötigt, um die Variable woanders benutzen zu können.

 

Beispiel:

int lives;

 

Initialisierung

Eine Variable kann gleich bei der Definition initialisiert werden, also einen Wert kriegen.

Einfach ein "= wert" zwischen Name und Semikolon quetschen.

Je nach Kontext wird das mal mehr, mal weniger als guter Programmierstil angesehen; für Unity ist das meist sehr gebräuchlich.

Der Wert kann sich später natürlich wieder ändern.

 

Beispiel:

int lives = 5;

 

Zugriffsmodifikatoren

Jetzt wird's interessant.

Ein Zugriffsmodifikator gibt an, wer alles diese Variable benutzen darf.

Für den Anfang relevant sind erst einmal nur public und private.

public gibt dabei an, dass alles und jeder den Wert der Variable herausfinden und ihn auch ändern kann.

private ist quasi das Gegenteil: Nur die Klasse, in der die Variable definiert ist, weiß überhaupt, dass es sie gibt.

 

Gibt man keinen Zugriffsmodifikator an, ist das in C# (!) gleichbedeutend mit private. Ob man private also hinschreibt oder nicht, ist also Geschmackssache.

 

Beispiel:

public Person bestFriend;

 

public ist immer mit etwas Vorsicht zu genießen. Grundsätzlich gilt: Je weniger eine Klasse von sich öffentlich macht, desto unwahrscheinlicher wird es, das eine andere Klasse etwas von außen vermurkst. Klassen sollen als Einheiten funktionieren und nicht eng verwoben mit drölf anderen Klassen sein.

Wann immer es allerdings völlig okay ist, wenn eine andere Klasse völlig uneingeschränkt den Wert einer Variablen ändert, benutzt in Unity ruhig public.

public hat allerdings in Unity einen Nebeneffekt, auf den ich später eingehen werde.

 

Static

Das Keyword static hat eine besondere Bedeutung, die eine Variable von ihrer Bedeutung her komplett woanders hin verschiebt.

Ich erklär's nochmal so kurz wie möglich:

Wenn man ein Klasse hat, und diese hat eine Variable:

class Person
{
 int alter;
}

...dann kann man mehrere Objekte dieser Klasse erstellen:

jemand = new Person();
jemandAnderes = new Person();

...und diese Objekte können unterschiedliche Werte für diese Variable haben.

jemand könnte als Alter 18 haben und jemandAnderes 42.

 

static hebt diesen Umstand auf und sagt: Diese Variable hat nicht pro Objekt einen eigenen Wert, sondern nur einen einzigen, der global gilt.

 

Anwendungsbeispiel:

class Checkpoint
{
 static int checkpointsLeft = 0;

 public void Initialise()
 {
++checkpointsLeft;
 }

 public void CheckpointTouched()
 {
--checkpointsLeft;
if(checkpointsLeft == 0)
{
  WinTheGame();
}
 }
}

Die Variable checkpointsLeft zählt hier, wie viele Checkpoints es (noch) gibt, und wann immer einer berührt wird, wird 1 abgezogen. Hat man alle Checkpoints berührt, gewinnt man.

Wäre die Variable nicht statisch (also mit static markiert), dann würde jeder Checkpoint seinen eigenen Wert für checkpointsLeft haben. So aber gibt es global nur eine Variable checkpointsLeft.

 

Alles, was man mit static machen kann, kann man irgendwie auch ohne machen. Auch static sollte nur dann eingesetzt werden, wenn es wirklich sinnvoll ist - da es aber einige Vorteile gegenüber den Alternativen bietet, kommt es immer mal wieder vor.

 

Zugriffsmodifikatoren und static lassen sich kombinieren:

public static int amount;

...aber gerade die Kombination public static ist fast immer ein schlechtes Zeichen ;)

 

C# für Unity

 

Jetzt kommt der Teil, der den C#-Standard erweitert, wann immer man Unity benutzt.

 

public

Wie erwähnt, hat public in Unity eine Sonderbedeutung: Öffentliche Variablen werden serialisiert und im Editor exponiert.

Das heißt, dass eine Variable mit public davor im Editor angezeigt wird (exponiert), man den Wert im Editor einstellen kann und dieser dann in der Szenendatei mitgespeichert wird (serialisiert).

Nnach dem Motto: "Dieses" GameObject hat "diese" Komponente (die ihr programmiert habt) und "diese" Variable davon hat "diesen" Wert.

 

So ziemlich jedes Unity-Scripting-Anfängertutorial zeigt einem das, aber der allgemeine Effekt von public (s.o.) wird gerne erst einmal unterschlagen.

 

Was macht man denn jetzt, wenn eine Variable vor Zugriff von anderen Klassen geschützt sein soll, aber trotzdem im Editor exponiert sein soll? Oder umgekehrt: Eine Variable, die public sein soll, aber immer denselben Startwert hat und damit im Editor nichts zu suchen hat?

Zum Glück gibt es dafür Lösungen.

 

Serialisierungs-Attribute

C# hat so genannte "Attribute", die man über Variablen, aber auch, je nach Attribut, vor Methoden und Klassen setzen kann. Sie sehen so aus:

[Attribut]
int zahl;

Für uns jetzt relevant sind [serializeField] und [system.NonSerialized].

Sie machen das, was man vermutet: [serializeField] sorgt für das, was public macht, nur eben auch bei privaten Variablen.

 

Beispiel:

[serializeField]
private int lives = 5;

 

Der umgekehrte Fall, dass eine Variable public sein soll, aber nicht im Editor auftauchen soll, kommt eher selten vor, aber falls doch, hilt [system.NonSerialized] auf gleiche Art.

 

Kleiner Zusatz für Fortgeschrittene: Propertys

 

Propertys sind "Dinger", die von außen so aussehen wie Variablen, aber wesentlich mehr können.

Die einfache Anwendungsform erlaubt es, Lesen uns Schreiben eines Variablenwertes mit unterschiedlichen Zugriffsmodifikatoren zu versehen:

public int lives { private set; get; }

Mit diesem Code ist lives von allen anderen Klassen auslesbar; den Wert ändern kann man allerdings nur von innerhalb der Klasse. get nimmt hierbei den Zugriffmodifikator der Property selbst an.

 

Benutzt werden Propertys, als wären es Variablen:

if(lives == 0)
// oder
lives = 5;

 

Propertys können noch mehr, aber zuerst zu den Einschränkungen:

1. Propertys können von sich aus nicht direkt initialisiert werden, da muss man tricksen

2. Propertys kann Unity nicht serialisieren, weder mit public, noch mit [serializeField].

 

Kommen wir direkt dazu, was Propertys noch können. Und zwar: Seiteneffekte.

Oft will man, dass etwas passiert, wenn sich ein Wert ändert; z.B. Tod, wenn die HP 0 erreichen.

Propertys können Code ausführen, wann immer der Wert ausgelesen oder geändert wird. Tatsächlich kann der Wert beim Auslesen überhaupt erst generiert werden!

Um so etwas zu erreichen, einfach geschweifte Klammern hinter get und/oder set schreiben.

 

Beispiel "Direkte Weitergabe":

public Color color
{
 get
 {
   return renderer.material.color;
 }
 set
 {
   renderer.material.color = value;
 }
}

Man bemerke hier die Verwendung von return und dem speziellen Keyword value.

 

Beispiel "Daten generieren":

private Konto[] konten;
public int gesamtVermoegen
{
 get
 {
   var result = 0;
   foreach(var konto in konten)
   {
  result += konto.saldo;
   }
   return result;
 }
}

Auffällig hier: Es gibt kein set. Das bedeutet, man kann die Variable nur auslesen, aber nicht einen Wert setzen. Natürlich kann man auf die Konten einzahlen, um den Wert zu ändern.

 

Beispiel "Gemischte Zugirffsmodifikatoren mit Serialisierung":

[serializeField]
private int _lives = 5;
public int lives
{
 get { return _lives; }
 private set { _lives = value; }
}

Dieser Code ist besonders nützlich: lives ist öffentlich auslesbar, aber nur privat änderbar.

_lives wird serialisiert. Der Unterstrich ist eine verbreitete Schreibweise für private Variablen (die ich in Unity allerdings nur in Verbindung mit Code wie diesem verwende) und wird beim Anzeigen im Editor entsprechend weg gelassen.

Von aussen sieht es damit aus, als gäbe es nur eine Variable lives, die im Editor zu sehen ist, deren Wert aber auf magische Weise nicht von anderen Klassen geändert werden kann.

 

Das war's dann für heute

 

Hoffentlich schafft diese kleine Auflistung etwas Klarheit darüber, wann man wie Variablen deklariert.

Frohes Schaffen! :)

  • Like 11

Share this post


Link to post
Share on other sites

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

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

Loading...
Sign in to follow this  

×
×
  • Create New...