Procedural Asset Management i enhet

Vi har sett tidligere på å legge til egne verktøy til Unitys redaktør; Nå, i denne korte opplæringen, vil jeg introdusere deg til å håndtere eiendelene ved hjelp av script i Unity. Vi styrer baner, lager prefab-filer, genererer en tekstur og lagrer den på et bilde. Til slutt vil vi også lage en materialfil som bruker det genererte bildet, og alt dette vil bli gjort med kode.


Endelig resultatforhåndsvisning

La oss se på det endelige resultatet vi vil jobbe for:


Trinn 1: Sett opp prosjektet

Lag et tomt prosjekt; Vi vil ikke bruke noe fancy her, så vi burde ikke plage å importere noe i det hele tatt. Når det er gjort, opprett et redigeringsskript. Enhet vil la oss bruke sine redaktørklasser bare hvis vi plasserer vårt skript i en mappe som heter Redaktør. Siden det ikke finnes i prosjektet vårt ennå, må vi opprette det.

La oss nå lage et skript inni det.


Trinn 2: Legg til en MenuItem

La oss rydde opp skriptet vårt. Bortsett fra grunnleggende funksjonalitet, vil vi også kunne bruke redaktørklassen. Vi må være bruker UnityEditor og skriptets klasse skal utvide Redaktør klasse i stedet for MonoBehaviour som vanlige spillobjekter gjør.

 bruker UnityEngine; bruker System.Collections; bruker UnityEditor; offentlig klasse Eksempler: Redaktør 

I vår første funksjon jobber vi med prefabs, la oss kalle det a PrefabRoutine.

 offentlig klasse Eksempler: Redaktør void PrefabRoutine () 

For å utføre denne funksjonen enkelt fra editoren, la oss legge den til som en MENUITEM.

 offentlig klasse Eksempler: Editor [MenuItem ("Eksempler / Prefab Routine")] void PrefabRoutine () 

Bortsett fra å la enheten vite at vi vil at denne funksjonen skal kunne kjøres fra Eksempler-> Prefab Routine ", Vi må også gjøre denne funksjonen statisk.

 offentlig klasse Eksempler: Editor [MenuItem ("Eksempler / Prefab Routine")] statisk tomrom PrefabRoutine () 

Hvis du går tilbake til redaktøren nå (og oppdaterer menyen), vil du legge merke til at det er en ny meny som heter eksempler der.

Hvis du velger Prefab Routine ingenting vil skje siden vår funksjon er tom.


Trinn 3: Opprett en mappe

For å forme vårt prosjekt slik vi ønsker, må vi vite hvordan du lager mapper slik at vi kan flytte ting rundt. Å lage en mappe fra skriptet er veldig grei, alt vi trenger å gjøre er å la enhet få vite hvor mappen skal plasseres. For å lage en mappe må vi bruke AssetDatabase klasse.

 [MenuItem ("Eksempler / Prefab Routine")] statisk tomrom PrefabRoutine () AssetDatabase.CreateFolder ("Assets", "Prefab Folder"); 

"Eiendeler" er navnet på den overordnede mappen i katalogen vi vil opprette. I vårt tilfelle er det hovedprosjektmappen der alle våre eiendeler er importert / opprettet.

Merk at du også kan bruke .NET Directory klasse. Dette lar deg også slette, flytte eller få tilgang til katalogfilene. For å bruke denne klassen må du være bruker System.IO.

Hver gang du velger Prefab Routine fra redaktøren skal en ny mappe opprettes og være synlig i prosjektvisningen.


Trinn 4: Lag en prefab

For å lage en prefab trenger vi å ringe EditorUtility.CreateEmptyPrefab (). Funksjonen tar prefab-banen som et argument.

 [MenuItem ("Eksempler / Prefab Routine")] statisk tomrom PrefabRoutine () AssetDatabase.CreateFolder ("Assets", "Prefab Folder"); Objekt prefab = EditorUtility.CreateEmptyPrefab ("Assets / Prefab Folder / obj.prefab"); 

Ikke glem forlengelsen! Også, etter at vi har opprettet filen, må vi ringe AssetDatabase.Refresh (), så enheten er i stand til å se den.

 [MenuItem ("Eksempler / Prefab Routine")] statisk tomrom PrefabRoutine () AssetDatabase.CreateFolder ("Assets", "Prefab Folder"); Objekt prefab = EditorUtility.CreateEmptyPrefab ("Assets / Prefab Folder / obj.prefab"); AssetDatabase.Refresh (); 

Hvis vi forlater en konstant bane som et argument, vil hver gang vi velger rutinen, erstatte en ny tom prefab det gamle. La oss tilordne hver prefab til å skille mappe for å motvirke det. For å gjøre dette må vi lagre den nylig opprettede mappen til en streng, slik at vi kan bruke den som en banargument senere. De Lag mappe funksjon returnerer a GUID, som i utgangspunktet er filens (eller katalogens) ID. Det er en funksjon som henter banen hvis vi sender inn denne IDen. Det heter GUIDToAssetPath; la oss bruke den til å få mappens sti.

 [MenuItem ("Eksempler / Prefab Routine")] Statisk tomrom PrefabRoutine () Stringbane = AssetDatabase.GUIDToAssetPath (AssetDatabase.CreateFolder ("Assets", "Prefab Folder")); Objekt prefab = EditorUtility.CreateEmptyPrefab ("Assets / Prefab Folder / obj.prefab"); AssetDatabase.Refresh (); 

La oss nå bruke sti å rette prefabsene vi skal lage til den nylig opprettede mappen.

 [MenuItem ("Eksempler / Prefab Routine")] Statisk tomrom PrefabRoutine () Stringbane = AssetDatabase.GUIDToAssetPath (AssetDatabase.CreateFolder ("Assets", "Prefab Folder")); Objekt prefab = EditorUtility.CreateEmptyPrefab (sti + "/obj.prefab"); AssetDatabase.Refresh (); 

Du kan teste om de opprettede tomme prefabsene er pakket i mapper nå.


Trinn 5: Still inn Prefab

Hvis du lager en prefab, vil du sannsynligvis ikke la den være tom, fordi det i så fall er ganske ubrukelig. La oss sette vår prefab hvis det er noe spillobjekt valgt mens rutinen vår utfører. Vi prefabrikerer til det valgte objektet. For å få valgt valgt objekt kan vi bruke utvalg klasse som har en referanse til det. For å sette prefaben må vi ringe ReplacePrefab ().

 [MenuItem ("Eksempler / Prefab Routine")] Statisk tomrom PrefabRoutine () Stringbane = AssetDatabase.GUIDToAssetPath (AssetDatabase.CreateFolder ("Assets", "Prefab Folder")); Objekt prefab = EditorUtility.CreateEmptyPrefab (sti + "/obj.prefab"); AssetDatabase.Refresh (); hvis (Selection.activeObject) EditorUtility.ReplacePrefab (Selection.activeGameObject, prefab); 

Hvis du kjører rutinen med et hvilket som helst spillobjekt som er valgt nå, vil du legge merke til at den opprettede prefab er automatisk innstilt.

Det er det, vi har laget en tilpasset rutine for prefab creation, det er ikke veldig nyttig, men du bør kunne vite hvordan du gjør det nå hvis det blir behov for en slik ting i prosjektet ditt.

På slutten vil jeg også nevne det AssetDatabase Du kan også flytte eiendeler rundt, flytte dem til søppel eller slette dem ved å ringe AssetDatabase.MoveAsset (), AssetDatabase.MoveAssetToTrash () og AssetDatabase.DeleteAsset () henholdsvis. Resten av funksjonaliteten finner du på AssetDatabase skriptreferanseside.


Trinn 6: Legg til en annen menyelement

La oss gå til et annet eksempel, denne gangen vil vi lage en tekstur og et materiale programmatisk. La oss ringe dette menyelementet Materiell rutine.

 [MenuItem ("Eksempler / Prefab Routine")] Statisk tomrom PrefabRoutine () Stringbane = AssetDatabase.GUIDToAssetPath (AssetDatabase.CreateFolder ("Assets", "Prefab Folder")); Objekt prefab = EditorUtility.CreateEmptyPrefab (sti + "/obj.prefab"); AssetDatabase.Refresh (); hvis (Selection.activeObject) EditorUtility.ReplacePrefab (Selection.activeGameObject, prefab);  [MenuItem ("Examples / Material Routine")] statisk tomrom MaterialRoutine () 

Nå har vi to elementer å velge mellom i eksempler Meny.


Trinn 7: Opprett en tekstur

La oss lage en Texture2D og sett størrelsen til (256, 256) for dette eksempelet.

 [MenuItem ("Eksempler / Material Rutine")] Statisk tomrom MaterialRoutine () Texture2D tex = Ny Texture2D (256, 256); 

Nå skal vi ikke la alle disse pikslene gå bort, så la oss sette teksturens piksler i henhold til en slags tankeformel formel. For det trenger vi to til sløyfer for å gå gjennom hver piksel. For å angi hver pikselfarge må vi ringe SetPixel () som tar posisjonen til pikselet på en tekstur og dens farge som argumenter.

 [MenuItem ("Eksempler / Material Rutine")] Statisk tomrom MaterialRoutine () Texture2D tex = Ny Texture2D (256, 256); for (int y = 0; y < 256; ++y)  for (int x = 0; x < 256; ++x) tex.SetPixel(x, y, new Color());  

For å tildele fargen bruker vi Mathf.Sin () funksjon. De Farge klassen kan initialiseres med tre flotter, henholdsvis henholdsvis de røde, grønne og blå fargekomponentene. Maks tillatt verdi er 1 og min er 0, så Synd() funksjonen passer perfekt til våre behov.

 for (int y = 0; y < 256; ++y)  for (int x = 0; x < 256; ++x) tex.SetPixel(Mathf.Sin(x*y), Mathf.Sin(x*y), Mathf.Sin(x*y))); 

Det spiller ingen rolle hva vi sender til Synd() funksjon, men for å få noe mer interessant, bør vi gi en verdi som endres for hver piksel.


Trinn 8: Opprett et bilde

La oss nå lage et bilde fra teksten vi nettopp har laget. Siden vi skal skrive til en fil i binær modus, må vi være bruker System.IO, så la oss legge den til toppen av skriptet vårt.

 bruker UnityEngine; bruker System.Collections; bruker UnityEditor; bruker System.IO; offentlig klasse Eksempler: Redaktør

For å lagre tekstur som en PNG bildet vi først må ringe EncodeToPNG () som vil returnere en rekke byte som PNG filen består av.

 for (int y = 0; y < 256; ++y)  for (int x = 0; x < 256; ++x) tex.SetPixel(x, y, new Color(Mathf.Sin(x*y), Mathf.Sin(x*y), Mathf.Sin(x*y)));  byte[] pngData = tex.EncodeToPNG();

Nå som vi har vår pngData vi kan skrive den til en fil og lage en PNG bildet på denne måten.

 byte [] pngData = tex.EncodeToPNG (); hvis (pngData! = null) File.WriteAllBytes ("Assets / texture.png", pngData);

Siden vi lager filen på en konstant bane, hver gang vi løper MaterialRoutine (), Teksten blir overskrevet.

Og siden vi har vårt bilde, trenger vi ikke den genererte teksten lenger, siden det ikke vil referere til et bilde uansett. La oss ødelegge det.

 byte [] pngData = tex.EncodeToPNG (); hvis (pngData! = null) File.WriteAllBytes ("Assets / texture.png", pngData); DestroyImmediate (tex);

Også, vi må la Unity oppdatere prosjektvisningen og filreferanser; å gjøre det vi trenger å ringe AssetDatabase.Refresh ().

 byte [] pngData = tex.EncodeToPNG (); hvis (pngData! = null) File.WriteAllBytes ("Assets / texture.png", pngData); DestroyImmediate (tex); AssetDatabase.Refresh ();

La oss teste om teksten blir opprettet når vi utfører rutinen vår.


Trinn 9: Lag et materiale

Vi har et bilde, og nå kan vi lage et materiale som bruker det som en tekstur. La oss lage en nytt materiale.

 AssetDatabase.Refresh (); nytt materiale (Shader.Find ("Diffuse"));

Det opprettede materialet vil bruke en diffuse shader. For å lagre dette materialet i filen, kan vi ringe AssetDatabase.CreateAsset (). Denne funksjonen tar en egenskap som det første argumentet, og banen som den andre.

 AssetDatabase.Refresh (); AssetDatabase.CreateAsset (nytt materiale (Shader.Find ("Diffuse")), "Assets / New Material.mat");

Hvis du kjører rutinen nå, ser du at materialet er opprettet.

Som du kan se alt er riktig, heter det Nytt materiale og den bruker diffuse shader, men det er ingen tekstur tildelt den.


Trinn 10: Tilordne strukturen

Først må vi få en referanse til materialet vi nettopp har laget. Vi kan få det ved å ringe AssetDatabase.LoadAssetAtPath () som laster eiendelen og returnerer sin referanse.

 AssetDatabase.CreateAsset (nytt materiale (Shader.Find ("Diffuse")), "Assets / New Material.mat"); Material materiale = (Material) (AssetDatabase.LoadAssetAtPath ("Assets / New Material.mat", typeof (Material)));

La oss nå tilordne vår genererte tekstur som materialets hovedstruktur. Vi kan få teksturreferansen til den genererte teksten på samme måte som vi har referansen til materialet.

 Material materiale = (Material) (AssetDatabase.LoadAssetAtPath ("Assets / New Material.mat", typeof (Material))); material.mainTexture = (Texture2D) (AssetDatabase.LoadAssetAtPath ("Assets / texture.png", typeof (Texture2D)));

For å se resultatene, kjør Materiell rutine.

Som du kan se, har materialet teksten tildelt nå.

Konklusjon

Det er slutten på introduksjonen for å administrere dine eiendeler ved hjelp av skript. Hvis du vil utvide din kunnskap om emnet, kan du besøke Unity Editor Classes referansesiden, spesielt AssetDatabase script referansen er verdt å se på. Hvis du trenger å jobbe på et lavt nivå, bør du også lese dokumentene på System.IO for å få mer informasjon om sine klasser og hvordan du kan bruke dem. Takk for din tid!