In Unity 5, was ist eine "saubere" Art, dynamisch erstellte Spielobjekte zu verwalten?Unity 5: Saubere Art, dynamisch erstellte GameObjects zu verwalten
Ich habe eine Komponente (MonoBehavior
) geschrieben, die mehrere GameObjects
erstellt/zerstört. Die Objekte werden als Teil des benutzerdefinierten Anpassungssystems geladen, das Teile des Charakters - Haare/Kleidung usw. - auswählt. Dies bedeutet, dass sie für den Spieler sichtbar sind, im Editor sichtbar sind, aber im Editor nicht editierbar sein sollen. Die geladenen Objekte sind Maschen mit Skeletten.
Das Skript verhält sich in dieser Art und Weise:
- Lasten Gameobjects von Ressourcen (genaues Objekt in Skript bestimmt wird, sind sie nicht prefabs)
- Hängt sie bis zu einem gewissen Teil der Szene (nicht unbedingt zu seinem eigener Knoten)
- Löscht, wenn zerstört.
Löschung:
protected void unloadLastResource(){
if (lastResourceInstance){
if (Application.isEditor){
GameObject.DestroyImmediate(lastResourceInstance);
}
else
GameObject.Destroy(lastResourceInstance);
Resources.UnloadUnusedAssets();
lastResourceInstance = null;
}
}
Creation:
GameObject target = getEffectiveTargetNode();
Object resource = Resources.Load(newResourceName);
instance = Instantiate(resource) as GameObject;
instance.hideFlags = HideFlags.HideAndDontSave;
instance.transform.parent = target.transform;
instance.transform.localPosition = Vector3.zero;
instance.transform.localRotation = Quaternion.identity;
instance.transform.localScale = Vector3.one;
Zerstörung Handler:
void OnDestroy(){
unloadLastResource();
}
, die im Editor zu funktionieren scheint, aber wenn ich wechseln von Gaming-Modus zurück Im Editiermodus erhalte ich viele Warnungen:
Destroying object multiple times. Don't use DestroyImmediate on the same object in OnDisable or OnDestroy.
UnityEngine.Object:DestroyImmediate(Object)
Und ich bekomme Haufen neuer Objektbäume (diejenigen, die gelöscht werden sollen - Bäume von Objekt stammen, die zusammen mit original „Ressourcen“ und wurde angebracht geladen wurde) auf der obersten Ebene der Szene hieararchy.
Also, wie handhabe ich dynamisch dynamisch erstellte Spielobjekte?
Ich muss wissen, welche Flags ich setzen muss und welche Schritte ich tun sollte, um sicherzustellen, dass das Objekt nicht in die Szene "leckt" und ordnungsgemäß zerstört wird, wenn ich die Komponente lösche, die es erstellt hat.
Beratung?
Vollbasisklasse, die von „Resource“
public class BaseResourceLoader : MonoBehaviour {
public GameObject targetNode = null;
protected GameObject lastTargetNode{
get{return lastTargetNodeInternal;}
}
private GameObject lastTargetNodeInternal = null;
protected bool targetNodeChanged(){
return targetNode != lastTargetNode;
}
protected string lastResourceName{
get{return lastResourceNameInternal;}
}
private string lastResourceNameInternal = "";
//private Object lastResource;
private GameObject lastResourceInstance;
protected GameObject getEffectiveTargetNode(){
if (targetNode == null)
return this.gameObject;
return targetNode;
}
public void reloadResource(){
loadNewResource(lastResourceNameInternal, true);
}
protected void unloadLastResource(){
if (lastResourceInstance){
if (Application.isEditor){
GameObject.DestroyImmediate(lastResourceInstance);
}
else
GameObject.Destroy(lastResourceInstance);
Resources.UnloadUnusedAssets();
lastResourceInstance = null;
}
lastResourceNameInternal = "";
}
protected void loadNewResource(string newResourceName, bool forceReload){
if ((newResourceName == lastResourceNameInternal) && !forceReload)
return;
GameObject instance = null;
if (newResourceName != ""){
GameObject target = getEffectiveTargetNode();
Object resource = Resources.Load(newResourceName);
instance = Instantiate(resource) as GameObject;
instance.hideFlags = HideFlags.HideAndDontSave;
instance.transform.parent = target.transform;
instance.transform.localPosition = Vector3.zero;
instance.transform.localRotation = Quaternion.identity;
instance.transform.localScale = Vector3.one;
}
unloadLastResource();
lastResourceInstance = instance;
lastResourceNameInternal = newResourceName;
lastTargetNodeInternal = targetNode;
}
void OnDestroy(){
unloadLastResource();
}
}
Danke für das Schnipsel. Ich analysiere es gerade und suche nach Unterschieden im Vergleich zu meinem Code (ich speichere auch Objektinstanzen in Variablen, damit sie dasselbe tun) – SigTerm
Ich habe dein Skript untersucht und herausgefunden, dass es genauso funktioniert Bergwerk. Ich habe das Problem herausgefunden, wenn Sie interessiert sind. Siehe die Antwort. – SigTerm