How legge til dine egne verktøy til Unity Redigerings
16
Del
20
Del
Denne Cyber Monday Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.
I denne opplæringen vil du lære hvordan du kan forlenge Unity3D redaktør slik at du kan gjøre bedre bruk av den i prosjektet. Du vil lære å tegne din egen dings, opprette og slette objekter i kode, opprette redaktør vinduer, bruke komponenter, og tillater brukeren å angre en handling de tar med skriptet.
Denne opplæringen forutsetter at du allerede vet det grunnleggende Unity arbeidsflyt. Hvis du vet hvordan du oppretter objekter, prefabs, scener, flytte rundt i editoren, feste komponenter så er du god til å gå!
Endelig resultat Forhåndsvisning
La oss ta en titt på det endelige resultatet vi skal jobbe mot:
Som du ser, vi skal lage en redigeringsvinduet, og en fargevelger der utvalget vi skal bruke til å tegne et rutenett. Vi vil også være i stand til å opprette og slette objekter, glefset til dette rutenettet, og angre slike handlinger
Trinn 1:. Gizmoer
Først vil vi lære å bruke dingser . Her er noen eksempler på innebygde dingser
Dette er den du vil sannsynligvis se mest i Unity, siden det er trukket for hvert objekt som har en Transform komponent knyttet til den -. Så i utgangspunktet hver valgt objektet vil ha dette gizmo trukket
Her er en annen dings, som gjør oss i stand til å se størrelsen på BoxCollider knyttet til spillet vårt objekt
Trinn 2:.. Lag en Grid Script
Lag en C # skript som vi kan bruke til å tegne vår egen dings for et objekt; Vi vil trekke en enkel nettet i editoren som et eksempel
hjelp UnityEngine, bruker System.Collections; public class Grid:. MonoBehaviour {void Start () {} void Update () {}}
For et rutenett vi må legge til to variabler, bredden og høyden
public class Grid:. MonoBehaviour {public float width = 32.0f; public float height = 32.0f; ugyldig Start () {} void Update () {}}
Å trekke i editoren vi trenger å bruke OnDrawGizmos tilbakeringing, så la oss lage det
public class Grid:. MonoBehaviour {public float width = 32.0f; public float height = 32.0f; ugyldig Start () {} void Update () {} void OnDrawGizmos () {}}
Trinn 3: Tegn Grid
Hvis du vil tegne et rutenett vi trenger et sett med horisontale og vertikale linjer og plasseringen av redaktørens kamera så vi vet rundt hvilket punkt bør vi trekke vår rutenett. . Først, la oss redde kameraets posisjon til en egen variabel
void OnDrawGizmos () {Vector3 pos = Camera.current.transform.position;}
Som du ser, kan vi få redaktørens kameraet ved hjelp av kamera .. .current referanse
Nå vi trenger to for looper som vil trekke de horisontale og vertikale linjer
void OnDrawGizmos () {Vector3 pos = Camera.current.transform.position; for (float y = pos.y - 800.0f; y < pos.y + 800.0f; y + = høyde) {Gizmos.DrawLine (ny Vector3 (-1000000.0f, Mathf.Floor (y /høyde) * høyde, 0.0 f), ny Vector3 (1000000.0f, Mathf.Floor (y /høyde) * høyde, 0.0f)); } For (float x = pos.x - 1200.0f; x < pos.x + 1200.0f; x + = bredde) {Gizmos.DrawLine (ny Vector3 (Mathf.Floor (x /bredde) * bredde, -1000000.0f, 0.0f), ny Vector3 (Mathf.Floor (x /bredde) * bredde, 1000000.0f, 0.0f)); }}
For å trekke linjer vi bruker Gizmos.DrawLine (). Merk at gizmoer klasse har mange andre tegne API metoder, så det er mulig å trekke slike primitive som kube eller kule eller selv deres trådmodeller. Du kan også tegne et bilde hvis du må.
Rutenettlinjene bør være uendelig lang, men float.positiveInfinity og float.negativeInfinity ikke synes å fungere godt med å tegne linjene, så vi kan bare sette vilkårlig store tall i stedet for dem. Også antall linjer strengt avhenge konstantene vi satt i for sløyfer definisjoner; teknisk vi ikke bør la de konstanter sånn, men det er bare en test kode
For å se rutenettet, opprette et tomt objekt og legge skriptet til det.
Trinn 4 : Opprett en egendefinert Inspector
Det neste du må dekke er å tilpasse inspektøren. For å gjøre det vi trenger for å lage en redaktør script. Opprett en ny C # fil og gi den navnet GridEditor Denne gangen har vi også trenge å bruke UnityEditor å kunne gjøre bruk av tekst klasser og funksjoner. Å overstyre standard inspektør for vår Grid objekt vi må legge til et attributt før vår klasse erklæring, [CustomEditor (typeof (Grid))] lar Unity vet at vi skal tilpasse Grids inspektør. For å kunne bruke redaktøren callbacks, må vi utlede fra redaktøren klassen i stedet for MonoBehaviour For å endre den nåværende inspektør vi trenger for å overstyre den gamle Hvis du sjekker nettet objektets inspektør i editoren nå, vil det være tom, selv om selve objektet har noen felles medlemmer. Det er fordi ved å overstyre OnInspectorGUI () vi forkastet standard inspektør for å lage en tilpasset en i stedet Før vi skaper noen områder vi trenger å få en referanse til objektet som inspektør gjelder. Vi har faktisk referanse allerede - det heter målet - men for enkelhets skyld vil vi lage en referanse til Grid komponent av dette objektet. Først, la oss erklære det Vi bør tildele den i OnEnable () funksjon som kalles så snart Inspektøren er aktivert La oss lage noen inspektør felt nå. Vi vil bruke GUILayout og EditorGUILayout klasser for at Den første linjen, GUILayout.BeginHorizontal (); viser at vi ønsker å plassere følgende inspektør elementer ved siden av hverandre, fra venstre til høyre. Som du kan forestille deg, den siste linjen, GUILayout.EndHorizontal (); indikerer at vi ikke lenger ønsker å gjøre det. Selve elementene er i mellom disse to linjene. Den første er en enkel etikett (i vårt tilfelle vil det være å vise Grid Bredde La oss se om feltet er lagt til inspektøren. La oss nå legge en mer element til inspektøren; denne gangen vil det bli grid.height Det ville være alt for våre nettobjekt felt, hvis du ønsker å vite om at du kan bruke i inspektøren så kan du besøke de Unity referanse sidene på EditorGUILayout og GUILayout andre felt og elementer . Legg merke til at de endringene vi gjør i vår nye inspektør er synlig først etter at vi velger Scene Vis vinduet. . Å gjøre dem synlige når de er laget vi kan kalle SceneView.RepaintAll () Nå har vi ikke trenger å klikke utenfor inspektør for å se resultatene av endringene Nå er vi bare trenger å få innspill Hendelses For ytterligere å spille med redaktøren skript vi trenger et spill objekt som vi vil være i stand til å bruke. La oss lage en enkel kube, og gjøre et ferdighus ut av det. Du kan matche størrelsen på rutenettet til kuben eller den andre veien rundt og justere det med et rutenett. Som du kan se, i hierarkiet visning kube Nå skal vi lage et objekt fra redaktøren manuset. La oss gå tilbake til vår GridEditor.cs Hotell og forlenge GridUpdate () -funksjonen. La oss lage objektet når nøkkelen en Som du ser, vi bare sjekke om hendelsen er et sentralt statlig endring og om tegnet som ble trykket er 'a'. Vi skaper også en referanse for vår nye objekt. Nå la oss instantiate det Selection.activeObject er en referanse til den markerte objektet i editoren. Hvis et objekt er valgt da vi bare klone den og endre den klone posisjon til (0.0, 0.0, 0.0). La oss teste om det fungerer. Du må være oppmerksom på én ting: vår GridUpdate () slutter å virke når eiendelene er gjeninnført /uthvilt, og for å aktivere det du har å velge objektet (for eksempel fra hierarkiet visning) at redaktøren manuset refererer til - i vårt eksempel er det Grid Alt vi klart å klone objektet, det klonede objektets link til ferdighus er ikke-eksisterende. Som du kan se, Cube (Clone) Før vi bruke denne funksjonen vi trenger for å få det valgte objektets ferdighus. For å gjøre det må vi bruke GetPrefabParent () som også tilhører EditorUtility klassen Vi kan også stoppe å sjekke om Selection.activeObject eksisterer, fordi hvis det ikke da ferdighus vil være lik null, og derfor kan vi komme unna med å sjekke bare prefab referanse. La oss nå instantiate vår prefab og sette sin posisjon Og det er det - la oss sjekke om det klonede kuben er knyttet til ferdighus nå The Event. klasse ikke la oss få vite hvor musen er i verden, det tilbyr bare skjermplass muse koordinater. Her er hvordan vi konvertere dem slik at vi kan få en tilnærmet verden plass mus posisjon Først bruker vi redaktørens kamera ScreenPointToRay å få ray fra skjermkoordinater, men dessverre før at vi trenger å oversette hendelsens plass på skjermen til en plass som er akseptabelt for ScreenPointToRay (). e.mousePosition holder musen posisjon i et koordinatsystem plass hvor øvre venstre hjørnet er (0, 0) poeng og nederst i høyre hjørne er lik (Camera.current.pixelWidth, -Camera.current.pixelHeight ). Vi trenger å oversette den til plassen der nederst Det neste vi skal gjøre er å redde ray opprinnelse til vår mousePos vektor, så det er lett tilgjengelig. Nå kan vi tildele klone stilling til hvor musen er. Legg merke til at når kameraet er stilt helt flatt da tilnærming av musen posisjon på den ene aksen er virkelig virkelig ille, det er derfor jeg setter z posisjon klone manuelt. Nå kuber bør opprettes hvor musen er Siden vi har fått vår grid satt opp, det ville være en skam ikke å bruke det; la oss bruke vår muse posisjon til å justere opprettet kuber til nettet Ta en titt på resultatet: I dette trinnet vi vil slette objekter programma i editoren. Vi kan gjøre det ved hjelp DestroyImmediate (). I dette eksempelet la oss gjøre en større bruk av markerings klasse og slette alle de valgte objektene når 'd' tasten trykkes Når 'd' tasten trykkes vi kjører gjennom alle de valgte objektene og slette hver enkelt av dem. Selvfølgelig kan vi også trykke Slett I dette trinnet vil vi gjøre bruk av angre klasse, som i utgangspunktet lar oss angre hver handling som vår redaktør script gjør. La oss starte med å løsne objektet skapelsen. For å være i stand til å ødelegge et objekt som vi opprettet i editor må vi kalle Undo.RegisterCreatedObjectUndo (). Det tar to argumenter: den første er objektet som har blitt skapt og den andre er navnet på angre. Navnet på handlingen som foregår alltid vises under til angres Rediger- >. Angre navn Hvis du lager et par terninger som bruker en Hvis vi ønsker å plassere hver opprettet objekt på en annen angre hendelsen og gjøre det mulig å angre skape dem én etter én må vi bruke Undo.IncrementCurrentEventIndex () Hvis du tester skriptet nå vil du se at kubene slettes en etter en ved å løsne deres skapelse Hvis du vil angre objektet sletting vi må bruke Undo.RegisterSceneUndo (). Det er en veldig treg funksjon som i hovedsak sparer scenen staten slik at vi senere kan gå tilbake til den tilstanden ved å utføre en angre handling. Dessverre ser det ut til å være den eneste måten for nå å få slettet gjenstander tilbake på scenen Undo.RegisterSceneUndo () tar bare ett argument, og det er angre navn. Etter sletting et par terninger med d Opprett et nytt manus, og la oss gjøre dette til en forlenge EditorWindow istedenfor Editor. La oss kalle det GridWindow.cs La oss lage en referanse til vår Grid Nå må vi opprette vinduet, vi kan gjøre det fra vår GridEditor I vår OnInspectorGUI () la oss legge til en knapp som vil skape GridWindow Vi bruker GUILayout å lage en knapp, har vi også satt knappens navn og bredde. Den GUILayout.Button returnerer sant når du trykker på knappen, hvis det er tilfelle så vi åpner vår GridWindow. Du kan gå tilbake til redaktøren og trykk på knappen i vår Grid objekt inspektør. Når du gjør det, GridWindow Før vi redigere alt fra vinduet vårt ., la oss legge til et fargefelt i vår Grid klasse, så vi kan redigere den senere Nå tildele Gizmos.color i OnDrawGizmos () -funksjonen Og nå la oss gå tilbake til GridWindow Greit, nå kan du sjekke om alt fungerer som det skal i editoren: Akkurat nå setter vi en delegat for å få inngangs hendelser fra scenen visningen vi bruker = tegnet, som ikke er en god metode for å gjøre det fordi det overstyrer alle andre tilbakeanrop. Vi bør bruke + = tegnet i stedet. La oss gå til vår GridEditor.cs Vi trenger også å opprette en OnDisable () tilbakeringing å fjerne vår GridUpdate (), hvis vi ikke gjør det så vil det hope seg opp og bli kalt flere ganger på en gang Det er det for innledningen til redaktøren scripting. Hvis du ønsker å utvide din knowladge, det er mye å lese om emnet i Unity Script Reference - kan det være lurt å sjekke Resources, AssetDatabase eller FileUtil klasser avhengig av dine behov Dessverre, noen klasser er. ennå udokumentert og på grunn av det, tilbøyelige til å endre uten å jobbe. For eksempel SceneView klasse og dens funksjoner eller Undo.IncrementCurrentEventIndex () funksjon fra Angre klassen. Dersom dokumentasjonen ikke gir de svarene du søker, vil du kanskje prøve å søke gjennom UnityAnswers eller Unity Forum. Takk for din tid! Anmeldelser
. Dette skriptet bør plasseres i Editor
mappe; hvis du ikke har en så skaper det nå
hjelp UnityEngine, bruker UnityEditor, bruker System.Collections [CustomEditor (typeof (Grid))] public class GridEditor. Editor {}
public class GridEditor:.. Editor {public styre void OnInspectorGUI () {}}
Trinn 5:. Bruk GUILayout å fylle Custom Inspector
public class GridEditor. Editor {Grid grid;
public class GridEditor: Editor {. Grid grid; public void OnEnable () {grid = (Grid) målet; }
public override void OnInspectorGUI () {GUILayout.BeginHorizontal (.); GUILayout.Label ("Grid bredde"); grid.width = EditorGUILayout.FloatField (grid.width, GUILayout.Width (50)); GUILayout.EndHorizontal ();}
tekst), og deretter ved siden av det vi skaper et EditorGUILayout.FloatField som er som du kan forestille deg en dupp felt. Merk at vi tilordner grid.width til verdien av at FloatField, og duppen feltet selv viser verdien av grid.width. Vi har også satt sin bredde 50 piksler
Trinn 6: Fyll Inspector og omlakker Scene
offentlig overstyring void OnInspectorGUI () {GUILayout.BeginHorizontal (.); GUILayout.Label ("Grid bredde"); grid.width = EditorGUILayout.FloatField (grid.width, GUILayout.Width (50)); GUILayout.EndHorizontal (); GUILayout.BeginHorizontal (); GUILayout.Label ("Grid Høyde"); grid.height = EditorGUILayout.FloatField (grid.height, GUILayout.Width (50)); GUILayout.EndHorizontal ();}
offentlig overstyring void OnInspectorGUI () {GUILayout.BeginHorizontal (); GUILayout.Label ("Grid bredde"); grid.width = EditorGUILayout.FloatField (grid.width, GUILayout.Width (50)); GUILayout.EndHorizontal (); GUILayout.BeginHorizontal (); GUILayout.Label ("Grid Høyde"); grid.height = EditorGUILayout.FloatField (grid.height, GUILayout.Width (50)); GUILayout.EndHorizontal (); SceneView.RepaintAll ();}
Trinn 7: Håndter Editor Input
public void OnEnable () {grid = (Grid) målet.; SceneView.onSceneGUIDelegate = GridUpdate;} void GridUpdate (SceneView sceneview) {}
annullere GridUpdate (SceneView sceneview) {Hendelses e = Event.current;.}
< h2> Trinn 8: Lag en Prefab
tekst er farget i blått; Dette betyr at den er koblet til et ferdighus. Du kan se at ferdighus i prosjektvinduet
Trinn 9:. Opprett et objekt fra redaktøren Script
trykkes.
Ugyldig GridUpdate (SceneView sceneview) {Hendelses e = Event.current; if (e.isKey & & e.character == 'a') {GameObject obj; }}
annullere GridUpdate (SceneView sceneview) {Hendelses e = Event.current.; if (e.isKey & & e.character == 'a') {GameObject obj; if (Selection.activeObject) {obj = (GameObject) instantiate (Selection.activeObject); obj.transform.position = new Vector3 (0.0f, 0.0f, 0.0f); }}}
objekt. Du må også huske at inngangs arrangementer vil bli fanget bare hvis Scene visningen er valgt
Trinn 10:. Bruke et Prefab fra redaktøren Script
navnet vises med vanlig svart skrift og det betyr at det ikke er koblet til den ferdighus som den opprinnelige kuben er. Hvis vi skulle kopiere den opprinnelige kuben manuelt i editoren, ville klonet kuben være knyttet til Cube
ferdighus. For å gjøre det fungere på denne måten for oss at vi må bruke InstantiatePrefab () -funksjonen fra EditorUtility klasse.
annullere GridUpdate (SceneView sceneview) {Hendelses e = Event.current.; if (e.isKey & & e.character == 'a') {GameObject obj; Objekt ferdighus = EditorUtility.GetPrefabParent (Selection.activeObject); if (ferdighus) {
annullere GridUpdate (SceneView sceneview) {Hendelses e = Event.current.; if (e.isKey & & e.character == 'a') {GameObject obj; Objekt ferdighus = EditorUtility.GetPrefabParent (Selection.activeObject); if (ferdighus) {obj = (GameObject) EditorUtility.InstantiatePrefab (ferdighus); obj.transform.position = new Vector3 (0.0f, 0.0f, 0.0f); }}}
Trinn 11: Trans Screen Mouse coords World coords
annullere GridUpdate (SceneView sceneview) {Hendelses e = Event.current.; Ray r = Camera.current.ScreenPointToRay (ny Vector3 (e.mousePosition.x, -e.mousePosition.y + Camera.current.pixelHeight)); Vector3 mousePos = r.origin;
venstre hjørnet er (0, 0) og øverst til høyre er (Camera.current.pixelWidth, Camera.current.pixelHeight), som er ganske enkel.
hvis (ferdighus) {obj = (GameObject) EditorUtility.InstantiatePrefab (ferdighus); obj.transform.position = new Vector3 (mousePos.x, mousePos.y, 0.0f);}
Trinn 12:. Juster Cubes til Grid
if (ferdighus) {obj = (GameObject) EditorUtility.InstantiatePrefab (ferdighus).; Vector3 justert = new Vector3 (Mathf.Floor (mousePos.x /grid.width) * grid.width + grid.width /2.0F, Mathf.Floor (mousePos.y /grid.height) * grid.height + grid.height /2.0f, 0.0f); obj.transform.position = justert;}
Trinn 13: ødelegge et objekt fra redaktøren Script
if (e.isKey & & e.character == 'a'). { GameObject obj; Objekt ferdighus = EditorUtility.GetPrefabParent (Selection.activeObject); if (ferdighus) {obj = (GameObject) EditorUtility.InstantiatePrefab (ferdighus); Vector3 justert = new Vector3 (Mathf.Floor (mousePos.x /grid.width) * grid.width + grid.width /2.0F, Mathf.Floor (mousePos.y /grid.height) * grid.height + grid.height /2.0f, 0.0f); obj.transform.position = justert; }} else if (e.isKey & & e.character == 'd') {foreach (GameObject obj i Selection.gameObjects) DestroyImmediate (obj);}
nøkkelen i redigeringsprogram til å slette disse objektene, men da disse ikke ville bli fjernet av vår script. Test det i redigereren
Trinn 14:. Angre objektforekomst
if (ferdighus) {obj = (GameObject) EditorUtility.InstantiatePrefab (ferdighus); Vector3 justert = new Vector3 (Mathf.Floor (mousePos.x /grid.width) * grid.width + grid.width /2.0F, Mathf.Floor (mousePos.y /grid.height) * grid.height + grid.height /2.0f, 0.0f); obj.transform.position = justert; Undo.RegisterCreatedObjectUndo (obj, "Create" + obj.name); }
nøkkel og deretter prøve å angre nå vil du legge merke til at alle de opprettede kuber har blitt slettet. Det er fordi alle disse opprettet kuber gikk inn i en enkelt angre hendelse
Trinn 15:. Angre Enkeltobjektforekomst
if (ferdighus) {Undo.IncrementCurrentEventIndex (.); obj = (GameObject) EditorUtility.InstantiatePrefab (ferdighus); Vector3 justert = new Vector3 (Mathf.Floor (mousePos.x /grid.width) * grid.width + grid.width /2.0F, Mathf.Floor (mousePos.y /grid.height) * grid.height + grid.height /2.0f, 0.0f); obj.transform.position = justert; Undo.RegisterCreatedObjectUndo (obj, "Create" + obj.name); }
Trinn 16:. Angre Object Slette
else if (e.isKey & & e.character == 'd'). {Undo.IncrementCurrentEventIndex (); Undo.RegisterSceneUndo ("Slett valgte objekter"); foreach (GameObject obj i Selection.gameObjects) DestroyImmediate (obj);}
tasten kan du angre på at slettingen
Trinn 17:. Lag redaktør Window Script
hjelp UnityEngine, bruker UnityEditor, bruker System.Collections; public class GridWindow. EditorWindow {public void init () {}}
objekt slik at vi får tilgang til den fra vinduet
public class GridWindow: EditorWindow {Grid grid;. public void Init () {grid = (Grid) FindObjectOfType (typeof (Grid)); }}
script
Trinn 18:. Opprett GridWindow
public override void OnInspectorGUI () {GUILayout.BeginHorizontal (.); GUILayout.Label ("Grid bredde"); grid.width = EditorGUILayout.FloatField (grid.width, GUILayout.Width (50)); GUILayout.EndHorizontal (); GUILayout.BeginHorizontal (); GUILayout.Label ("Grid Høyde"); grid.height = EditorGUILayout.FloatField (grid.height, GUILayout.Width (50)); GUILayout.EndHorizontal (); if (GUILayout.Button ("Open Grid Window", GUILayout.Width (255))) {GridWindow vindu = (GridWindow) EditorWindow.GetWindow (typeof (GridWindow)); window.Init (); } SceneView.RepaintAll ();}
skal dukke opp
Trinn 19:. Lag et fargefelt i GridWindow
public class Grid: MonoBehaviour {public float width = 32.0f; public float height = 32.0f; offentlig Color color = Color.white;.
void OnDrawGizmos () {Vector3 pos = Camera.current.transform.position; Gizmos.color = farge;
manus og lage et fargefelt der, så vi kan velge farge i vinduet. Vi kan gjøre det i OnGUI () tilbakeringing
public class GridWindow. EditorWindow {Grid grid; public void Init () {grid = (Grid) FindObjectOfType (typeof (Grid)); } Void OnGUI () {grid.color = EditorGUILayout.ColorField (grid.color, GUILayout.Width (200)); }}
Trinn 20: Legg en delegat
manus og gjøre denne endringen
public void OnEnable () {grid = (Grid) målet.; SceneView.onSceneGUIDelegate + = GridUpdate;.}
public void OnEnable () {grid = (Grid) målet; SceneView.onSceneGUIDelegate + = GridUpdate;} public void OnDisable () {SceneView.onSceneGUIDelegate - = GridUpdate;}
Konklusjon