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 
 
 
 

