unity3d
ScriptableObject
Suche…
Bemerkungen
ScriptableObjects mit AssetBundles
Achten Sie beim Hinzufügen von Prefabs zu AssetBundles, wenn diese Verweise auf ScriptableObjects enthalten. Da ScriptableObjects im Wesentlichen Assets sind, erstellt Unity Duplikate davon, bevor diese zu AssetBundles hinzugefügt werden. Dies kann zu unerwünschtem Verhalten während der Laufzeit führen.
Wenn Sie ein solches GameObject von einem AssetBundle laden, müssen Sie möglicherweise die ScriptableObject-Assets erneut in die geladenen Skripts einfügen, um die gebündelten zu ersetzen. Siehe Abhängigkeitseinspritzung
Einführung
ScriptableObjects sind serialisierte Objekte, die nicht an Szenen oder Spielobjekte gebunden sind, wie dies bei MonoBehaviours der Fall ist. Eine Möglichkeit: Es handelt sich um Daten und Methoden, die an Asset-Dateien in Ihrem Projekt gebunden sind. Diese ScriptableObject-Assets können an MonoBehaviours oder andere ScriptableObjects übergeben werden, wo auf ihre öffentlichen Methoden zugegriffen werden kann.
Aufgrund ihrer Beschaffenheit als serialisierte Assets eignen sie sich hervorragend für Manager-Klassen und Datenquellen.
ScriptableObject-Assets erstellen
Nachfolgend finden Sie eine einfache ScriptableObject-Implementierung.
using UnityEngine;
[CreateAssetMenu(menuName = "StackOverflow/Examples/MyScriptableObject")]
public class MyScriptableObject : ScriptableObject
{
[SerializeField]
int mySerializedNumber;
int helloWorldCount = 0;
public void HelloWorld()
{
helloWorldCount++;
Debug.LogFormat("Hello! My number is {0}.", mySerializedNumber);
Debug.LogFormat("I have been called {0} times.", helloWorldCount);
}
}
Indem CreateAssetMenu
Attribut CreateAssetMenu
zur Klasse hinzufügt, listet es das Untermenü Assets / Create auf . In diesem Fall ist es unter Assets / Create / StackOverflow / Beispiele .
Einmal erstellt, können ScriptableObject-Instanzen über den Inspector an andere Scripts und ScriptableObjects übergeben werden.
using UnityEngine;
public class SampleScript : MonoBehaviour {
[SerializeField]
MyScriptableObject myScriptableObject;
void OnEnable()
{
myScriptableObject.HelloWorld();
}
}
Erstellen Sie ScriptableObject-Instanzen durch Code
Sie erstellen neue ScriptableObject-Instanzen über ScriptableObject.CreateInstance<T>()
T obj = ScriptableObject.CreateInstance<T>();
Wo T
ScriptableObject
.
Erstellen Sie keine ScriptableObjects, indem Sie ihre Konstruktoren aufrufen.
new ScriptableObject()
.
Das Erstellen von ScriptableObjects mithilfe von Code zur Laufzeit ist selten erforderlich, da der Hauptzweck die Datenserialisierung ist. Sie können an dieser Stelle genauso gut Standardklassen verwenden. Dies ist häufiger, wenn Sie Editorerweiterungen mit Skripts erstellen.
ScriptableObjects werden auch im PlayMode im Editor serialisiert
Beim Zugriff auf serialisierte Felder in einer ScriptableObject-Instanz ist besondere Vorsicht geboten.
Wenn ein Feld mit SerializeField
als public
gekennzeichnet oder serialisiert ist, ist die Änderung des Werts dauerhaft. Sie werden beim Beenden des Playmode nicht wie bei MonoBehaviours zurückgesetzt. Dies kann manchmal nützlich sein, aber es kann auch ein Durcheinander verursachen.
Aus diesem Grund ist es am besten, serialisierte Felder schreibgeschützt zu machen und öffentliche Felder vollständig zu vermeiden.
public class MyScriptableObject : ScriptableObject
{
[SerializeField]
int mySerializedValue;
public int MySerializedValue
{
get { return mySerializedValue; }
}
}
Wenn Sie öffentliche Werte in einem ScriptableObject speichern möchten, die zwischen Wiedergabesitzungen zurückgesetzt werden, sollten Sie das folgende Muster in Betracht ziehen.
public class MyScriptableObject : ScriptableObject
{
// Private fields are not serialized and will reset to default on reset
private int mySerializedValue;
public int MySerializedValue
{
get { return mySerializedValue; }
set { mySerializedValue = value; }
}
}
Vorhandene ScriptableObjects zur Laufzeit finden
Um aktive ScriptableObjects zur Laufzeit zu finden, können Sie Resources.FindObjectsOfTypeAll()
.
T[] instances = Resources.FindObjectsOfTypeAll<T>();
Dabei ist T
der Typ der von Ihnen durchsuchten ScriptableObject-Instanz. Aktiv bedeutet, dass es zuvor in irgendeiner Form in den Speicher geladen wurde.
Diese Methode ist sehr langsam. Denken Sie daran, den Rückgabewert zwischenzuspeichern und den Aufruf nicht zu häufig zu machen. Ein direkter Verweis auf ScriptableObjects in Ihren Skripts sollte Ihre bevorzugte Option sein.
Tipp: Sie können Ihre eigenen Instanzsammlungen verwalten, um schneller nachschlagen zu können.
OnEnable()
Sie Ihre ScriptableObjects sich währendOnEnable()
in einer gemeinsam genutzten SammlungOnEnable()
.