Jump to content
Unity Insider Forum
Mark

Szenenübergreifende Variablen

Recommended Posts

Um Variablen auch dann noch benutzen zu können wenn man eine Szene wechselt müssen diese speziell behandelt werden, hier sind einige Möglichkeiten:

 

Statische Variablen:

Mithilfe des static Keywords werden variablen statisch und behalten somit ihren Wert solange bis entweder die AppDomain entladen wurde (Spiel wird beendet, Player/Editor Modus Wechsel in Unity) oder der Thread in dem sie erstellt wurden beendet wurde (ThreadStorage static).

 

Statische Variablen sind an keine Objektinstanz gebunden und überleben damit auch wenn es keine Instanz einer Klasse mehr gibt. Kurz und Knapp:

 

Statische Variablen sind Globale Variablen die nur innerhalb einer Klasse definiert werden um einen Zugriffspunkt auf sie zu bekommen. Die Klasse selbst spielt dabei nur eine Rolle wenn es darum geht Zugriffsbeschränkungen zu haben (public, private, internal, protected) und ist damit nur eine Art namespace.

 

public static float Score = 0;

 

Man verwendet statische Variablen indem man den Klassennamen anstatt des Klasseninstanznamens verwendet, in dem sich die statische Variable befindet.

Klasse.Variable = ...;

 

Für Fortgeschrittene Benutzer:

Möchte man statische Variablen benutzen und dennoch in verschiedenen Threads einen anderen Wert haben so benötigt man das ThreadStaticAttribute:

 

[ThreadStatic]
public static float Score = 0;

 

Damit hat der Score Wert in jedem Thread einen anderen Wert.

 

Statische Variablen haben den Vorteil dass sie sehr einfach zu verwenden sind. Der Nachteil allerdings ist dass sie überverwendet werden und damit einen eher schlechten Programmierstil fördern.

 

Auch ist das managen der Lebenszeit dieser Variablen nicht möglich, zB müssen alle statischen Variablen explizit neu gesetzt werden wenn man sie resetten möchte, was bei vielen statischen variablen viel Schreibarbeit ist.

Statische Variablen sind auch nicht persistent und verschwinden damit unwiederruflich nach Programmende.

 

DontDestroyOnLoad:

http://docs.unity3d....troyOnLoad.html

 

Mithilfe dieser Methode kann man ein ganzes Unity.Object davor bewahren bei einem Szenenwechsel zerstört zu werden. Komponenten sind zB solche Unity.Objects.

 

void Awake()
{
 DontDestroyOnLoad(gameObject);
}

 

Wenn man ein solches Objekt dennoch löschen möchte muss man dies manuell erledigen, indem entweder das Containerobjekt (ein GameObjekt im Falle eines MonoBehaviours)

zerstört wird oder das vor dem Löschen bewahrte Objekt selbst. Dazu kann man Destroy und/order DestroyImmediate benutzen.

 

Destroy(gameObject);

 

Auch hier verschwinden die Variablen natürlich wenn das Programm beendet wird wie bei den statischen Variablen.

 

PlayerPrefs:

Um Daten persistent zu speichern und wieder zu laden ist es nötig das speichern und laden selbst zu implementieren. Es gibt zum Glück im AssetStore genügent Tools die einen dies erleichtern. Aber auch Unity selbst liefert eine kleine Hilfestellung, die PlayerPrefs:

http://docs.unity3d....layerPrefs.html

 

PlayerPrefs.SetInt("Score", Score);

 

Score = PlayerPrefs.GetInt("Score");

 

Damit werden die Daten lokal gespeichert und können auch wieder geladen werden.

 

WWW Klasse:

Um die daten global zu laden und zu speichern benötigt man wiederum etwas mehr als das was Unity bietet. zB benötigt man entweder einen eigenen Webserver oder ein über Netzwerkmethoden erreichbares Interface. Mithilfe von NodeJS oder anderen Frameworks lässt sich relativ einfach ein solcher Webserver aufbauen.

 

Hat man also einen eigenen Webserver und entsprechende Schnittstellen kann man zB die WWW Klasse von Unity verwenden um Daten auf den Server zu oder herabzu laden.

http://docs.unity3d....erence/WWW.html

 

var scoreByteData = System.BitConverter.GetBytes(Score);

// POST Request
var www = new WWW("http://www.mydomain.de/api/score", scoreByteData);

 

// GET Request
var www = new WWW("http://www.mydomain.de/api/score");
...
Score = System.BitConverter.ToSingle(www.bytes, 0);

  • Like 9

Share this post


Link to post
Share on other sites

Gute Idee, darüber zu schreiben, aber ich finde, dass der Kernpunkt zu static irgendwie fehlt: Dass es Objektbindungen verhindert. Das Problem ist nicht, dass es schlechten Programmierstil fördert, sondern dass viele nicht wissen, was static genau macht und wann es entsprechend angebracht ist und wann nicht.

Share this post


Link to post
Share on other sites

Hi,

ein anderer cooler Trick für Szenenübergreifende Variablen ist das Verwenden von Scriptable-Objects. Dadurch vermeidet man jeweils das benutzen von Static-Variablen und erhöht jeweils die Flexibilität:

Hier wird jeweils das ScriptableObject angelegt:

//...
[CreateAssetMenu]
public class FloatVariable : ScriptableObject
{
	public float Value;
}

Der Vorteil ist im Project kann man mehr ScriptableObjects angelegen und die beliebig wo man sie benötigt reinlegen oder switchen:

Hier ist jeweils der benötigte Wert mit dem man weiter arbeitet. Der kann vom Inspector gesetzt werden.

using UnityEngine;

public class UnitAttackBehaviour : MonoBehaviour
{
	[SerializeField]
	private FloatVariable _damage;
  	//...
}

0sHE96AS.JPG

Mfg.

-John

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...

×
×
  • Create New...