2017-09-20 2 views
0

Ich versuche, Skripte im Bearbeitungsmodus in meinem Unity-Projekt zu implementieren. Die Idee ist, dass ein Skript an ein Objekt angehängt werden kann, und während es bearbeitet wird, können Attribute wie Maßstab/Position/Rotation aktualisiert werden.Dynamische Erstellung einer CustomEditor-Klasse in Unity/C#

Ohne ein Bearbeitungsmodus-Skript zu schreiben, sind all diese Dinge möglich, aber die Änderungen sind erst sichtbar, wenn die Wiedergabetaste gedrückt wird. Das ist der Unterschied hier.

Ich verwende eine Variation des Skripts zur Verfügung gestellt here, um dies zu tun.

Zunächst einmal habe ich ein MonoBehavior Skript zu meinem Spiel Objekt angebracht - es sieht aus wie so:

using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 

[ExecuteInEditMode] 
public class FlippersEditMode : MonoBehaviour { 
    public float extraScale = 1f; 
    public void updateEditorState() { 
     transform.localScale = (Vector3.up * extraScale); 
    } 
} 

Zweite ich ein Skript im Editor-Ordner haben, der diese updateEditorState Methode aufruft, wenn eine Schaltfläche „Aktualisieren“ gedrückt wird:

using UnityEngine; 
using UnityEditor; 

[CustomEditor(typeof(FlippersEditMode))] 
public class FlipperEditModeMeta: Editor { 
    public override void OnInspectorGUI() { 
     base.OnInspectorGUI(); 
     if (GUILayout.Button("Update")) { 
      if (target.GetType() == typeof(FlippersEditMode)) { 
       FlippersEditMode flippers = (FlippersEditMode)target; 
       flippers.updateEditorState(); 
      } 
     } 
    } 
} 

Dies funktioniert gut, und ich bin dafür dankbar, aber das letzte Stück Code ist reiner Textvorschlag. Ich brauche eine fast identische Datei für jedes Skript, das ich bearbeiten möchte.

Also begann ich zu versuchen, ein "Meta" Editor-Skript zu machen. Die Idee ist, dass dieses Skript ein Array von Slots hat, in die der Entwickler Skripte ziehen kann. Jedes hier gezogene Skript erhält eine CustomEditor-Klasse, die wie oben beschrieben definiert ist. Natürlich müssten die Klassen, die hier gezogen werden, updateEditorState implementieren, aber das ist die einzige Anforderung des Protokolls.

Also, wenn ich einen anderen Editor Skript, das wie folgt aussieht:

using UnityEngine; 
using UnityEditor; 

[CustomEditor(typeof(EditModeScripts))] 
public class EditModeScriptsMeta : Editor { 
    public override void OnInspectorGUI() { 
     base.OnInspectorGUI(); 
     if (GUILayout.Button("Update")) { 
      if (target.GetType() == typeof(EditModeScripts)) { 
       EditModeScripts edit_mode_scripts = (EditModeScripts)target; 
       edit_mode_scripts.updateEditorState() 
      } 
     } 
    } 
} 

Dann kann ich die updateEditorState Funktion im folgenden auslösen:

using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 
using UnityEditor; 

public class EditModeScripts : MonoBehaviour { 

    public MonoBehaviour[] scripts = {}; 

    public void updateEditorState() { 
     for (int i = 0; i < scripts.Length; i++) { 
      MonoBehaviour script = scripts[i]; 
      // How to generate an editor class here for each script? 
     } 
    } 
} 

Aber wie Sie ich kann nicht sehen, wissen, wie man die Klassen dynamisch generiert.

Antwort

1

Ich denke nicht, dass Ihr Ansatz wird rein dynamisch arbeiten. Unity kompiliert Ihren Code jedes Mal, wenn Sie etwas ändern und zur Einheit zurückkehren. Nach dem Kompilieren verwendet Unity Reflection, um festzustellen, welche Editoren verfügbar sind.

Sie könnten theoretisch neue Quelldateien erstellen, die den Editor-Code enthalten. Ich weiß nicht, ob es die Skripte automatisch reimportieren wird oder Sie den Reimport manuell auslösen müssen.

Für manuell neu zu importieren Sie eine Kombination aus AssetDatabase.Refresh() verwenden können und wenn das nicht genug ist, wählen Sie das Skript Asset über die Selection Klasse und lösen den Re-Import Menüeintrag mit EditorApplication.ExecuteMenuItem.