Gestione delle risorse procedurali in unità

In precedenza abbiamo cercato di aggiungere i nostri strumenti all'editor di Unity; ora, in questo breve tutorial, ti presenterò a gestire le risorse tramite script in Unity. Gestiremo percorsi, creeremo file prefabbricati, genereremo una trama e la salviamo su un'immagine. Infine creeremo anche un file materiale che utilizza l'immagine generata, e tutto ciò sarà fatto per codice.


Anteprima del risultato finale

Diamo un'occhiata al risultato finale su cui lavoreremo:


Passaggio 1: impostare il progetto

Crea un progetto vuoto; non useremo nulla di particolare qui, quindi non dovremmo preoccuparci di importare nulla. Fatto ciò, crea uno script di editor. Unity ci permetterà di usare le sue classi di editor solo se mettiamo il nostro script in una cartella chiamata editore. Dal momento che ciò non esiste ancora nel nostro progetto, dobbiamo crearlo.

Ora creiamo uno script al suo interno.


Passaggio 2: aggiungere un oggetto Menu

Puliamo il nostro script. A parte le funzionalità di base, vogliamo anche essere in grado di utilizzare le classi dell'editor. Dobbiamo essere usando UnityEditor e la classe del nostro script dovrebbe estendere il editore classe invece di MonoBehaviour come fanno gli oggetti normali del gioco.

 usando UnityEngine; usando System.Collections; usando UnityEditor; esempi di classe pubblica: Editor 

Nella nostra prima funzione lavoreremo con i prefabbricati, chiamiamolo a PrefabRoutine.

 public class Esempi: Editor void PrefabRoutine () 

Per eseguire facilmente questa funzione dall'editor, aggiungiamola come a Elemento del menu.

 public class Esempi: Editor [MenuItem ("Esempi / Prefab Routine")] void PrefabRoutine () 

Oltre a far sapere all'unità che vogliamo che questa funzione sia eseguibile dal Esempi-> Routine prefabbricata ", dobbiamo anche rendere statica questa funzione.

 public class Esempi: Editor [MenuItem ("Esempi / Prefab Routine")] static void PrefabRoutine () 

Se torni all'editor ora (e aggiorni il menu), noterai che c'è un nuovo menu chiamato Esempi Là.

Se si seleziona il Routine prefabbricata non succederà nulla poiché la nostra funzione è vuota.


Passaggio 3: creare una cartella

Per dare forma al nostro progetto nel modo in cui vogliamo, dobbiamo sapere come creare cartelle in modo da poter spostare le cose. Creare una cartella dallo script è molto semplice, tutto ciò che dobbiamo fare è far sapere all'unità dove deve essere posizionata la cartella. Per creare una cartella dobbiamo usare AssetDatabase classe.

 [MenuItem ("Esempi / Prefab Routine")] static void PrefabRoutine () AssetDatabase.CreateFolder ("Assets", "Prefab Folder"); 

"Risorse" è il nome della cartella principale della directory che vogliamo creare. Nel nostro caso è la cartella principale del progetto in cui vengono importati / creati tutti i nostri beni.

Si noti che è anche possibile utilizzare .NET elenco classe. Ciò consentirà anche di eliminare, spostare o accedere ai file delle directory. Per usare questo corso devi essere usando System.IO.

Ogni volta che selezioni il Routine prefabbricata dall'editor, una nuova cartella dovrebbe essere creata ed essere visibile nella vista del progetto.


Passaggio 4: creare un prefabbricato

Per creare un prefabbricato dobbiamo chiamare EditorUtility.CreateEmptyPrefab (). La funzione prende il percorso del prefabbricato come argomento.

 [MenuItem ("Esempi / Prefab Routine")] static void PrefabRoutine () AssetDatabase.CreateFolder ("Assets", "Prefab Folder"); Object prefab = EditorUtility.CreateEmptyPrefab ("Assets / Prefab Folder / obj.prefab"); 

Non dimenticare l'estensione! Inoltre, dopo aver creato il file, dobbiamo chiamare AssetDatabase.Refresh (), quindi l'unità è in grado di vederlo.

 [MenuItem ("Esempi / Prefab Routine")] static void PrefabRoutine () AssetDatabase.CreateFolder ("Assets", "Prefab Folder"); Object prefab = EditorUtility.CreateEmptyPrefab ("Assets / Prefab Folder / obj.prefab"); AssetDatabase.Refresh (); 

Se lasciamo un percorso costante come argomento, ogni volta che selezioniamo la nostra routine, un nuovo prefabbricato vuoto sostituirà il vecchio. Assegniamo ogni prefabbricato a una cartella separata per contrastarlo. Per fare questo abbiamo bisogno di salvare la cartella creata più di recente in una stringa in modo che possiamo usarla come argomento del percorso in seguito. Il Creare una cartella la funzione restituisce a GUID, che in pratica è l'ID del file (o della directory). C'è una funzione che recupera il percorso se inviamo questo ID. È chiamato GUIDToAssetPath; usiamolo per ottenere il percorso della nostra cartella.

 [MenuItem ("Esempi / Prefab Routine")] static void PrefabRoutine () string path = AssetDatabase.GUIDToAssetPath (AssetDatabase.CreateFolder ("Assets", "Prefab Folder")); Object prefab = EditorUtility.CreateEmptyPrefab ("Assets / Prefab Folder / obj.prefab"); AssetDatabase.Refresh (); 

Ora usiamo il sentiero per dirigere i prefabbricati che creeremo nella cartella creata più di recente.

 [MenuItem ("Esempi / Prefab Routine")] static void PrefabRoutine () string path = AssetDatabase.GUIDToAssetPath (AssetDatabase.CreateFolder ("Assets", "Prefab Folder")); Object prefab = EditorUtility.CreateEmptyPrefab (percorso + "/obj.prefab"); AssetDatabase.Refresh (); 

È possibile verificare se i prefabbricati vuoti creati sono ora raggruppati in cartelle.


Passaggio 5: impostare il prefabbricato

Se crei un prefabbricato, probabilmente non vuoi lasciarlo vuoto perché in quel caso è praticamente inutile. Impostiamo il nostro prefabbricato se c'è qualche oggetto di gioco selezionato mentre la nostra routine è in esecuzione. Faremo il prefabbricato all'oggetto selezionato. Per ottenere l'oggetto attualmente selezionato possiamo usare il Selezione classe che ha un riferimento ad esso. Per impostare il prefabbrato dobbiamo chiamare ReplacePrefab ().

 [MenuItem ("Esempi / Prefab Routine")] static void PrefabRoutine () string path = AssetDatabase.GUIDToAssetPath (AssetDatabase.CreateFolder ("Assets", "Prefab Folder")); Object prefab = EditorUtility.CreateEmptyPrefab (percorso + "/obj.prefab"); AssetDatabase.Refresh (); if (Selection.activeObject) EditorUtility.ReplacePrefab (Selection.activeGameObject, prefab); 

Se si esegue la routine con qualsiasi oggetto di gioco selezionato ora, si noterà che il prefabbricato creato viene impostato automaticamente.

Ecco, abbiamo creato una routine personalizzata per la creazione di prefabbricati, non è molto utile ma dovresti essere in grado di sapere come farlo ora se ci sarà bisogno di una cosa del genere nel tuo progetto.

Alla fine voglio anche dirlo AssetDatabase consente inoltre di spostare le risorse in giro, spostarle nel cestino o eliminarle chiamando AssetDatabase.MoveAsset (), AssetDatabase.MoveAssetToTrash () e AssetDatabase.DeleteAsset () rispettivamente. Il resto della funzionalità può essere trovato al AssetDatabase pagina di riferimento dello script.


Passaggio 6: aggiungere un'altra voce di menu

Andiamo a un altro esempio, questa volta creeremo una trama e un materiale a livello di programmazione. Chiamiamo questa voce di menu Routine materiale.

 [MenuItem ("Esempi / Prefab Routine")] static void PrefabRoutine () string path = AssetDatabase.GUIDToAssetPath (AssetDatabase.CreateFolder ("Assets", "Prefab Folder")); Object prefab = EditorUtility.CreateEmptyPrefab (percorso + "/obj.prefab"); AssetDatabase.Refresh (); if (Selection.activeObject) EditorUtility.ReplacePrefab (Selection.activeGameObject, prefab);  [MenuItem ("Esempi / routine materiale")] static void MaterialRoutine () 

Ora abbiamo due elementi tra cui scegliere Esempi menu.


Passaggio 7: creare una trama

Creiamo a Texture2D e impostare le sue dimensioni a (256, 256) per questo esempio.

 [MenuItem ("Esempi / routine materiale")] static void MaterialRoutine () Texture2D tex = new Texture2D (256, 256); 

Ora non dovremmo lasciare che tutti quei pixel vadano sprecati, quindi impostiamo i pixel della trama in base a qualche tipo di formula pensata. Per questo ci serviranno due per cicli per passare attraverso ogni pixel. Per impostare il colore di ciascun pixel, dobbiamo chiamare SetPixel () che prende la posizione del pixel su una trama e il suo colore come argomenti.

 [MenuItem ("Esempi / routine materiale")] static void MaterialRoutine () Texture2D tex = new Texture2D (256, 256); per (int y = 0; y < 256; ++y)  for (int x = 0; x < 256; ++x) tex.SetPixel(x, y, new Color());  

Per assegnare il colore useremo il Mathf.Sin () funzione. Il Colore la classe può essere inizializzata con tre float, corrispondenti rispettivamente alle componenti di colore rosso, verde e blu. Il valore massimo consentito è 1 e il minimo è 0, così la Peccato() la funzione si adatta perfettamente alle nostre esigenze.

 per (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))); 

Non importa ciò che ci sottomettiamo al Peccato() funzione, ma per ottenere qualcosa di più interessante dovremmo dare un valore che cambia per ogni pixel.


Passaggio 8: creare un'immagine

Ora creiamo un'immagine dalla texture che abbiamo appena creato. Dato che scriveremo in un file in modalità binaria, dobbiamo esserlo usando System.IO, quindi aggiungiamolo all'inizio del nostro script.

 usando UnityEngine; usando System.Collections; usando UnityEditor; using System.IO; esempi di classe pubblica: Editor

Per salvare la nostra texture come PNG immagine dobbiamo prima chiamare EncodeToPNG () che restituirà una matrice di byte che il PNG il file è composto da.

 per (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();

Ora che abbiamo il nostro pngData possiamo scrivere su un file e creare a PNG immagine in questo modo.

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

Poiché creiamo il file su un percorso costante, ogni volta che eseguiremo MaterialRoutine (), la trama verrà sovrascritta.

E dal momento che abbiamo la nostra immagine, non abbiamo più bisogno della texture generata in quanto non farà comunque riferimento a un'immagine. Distruggiamolo.

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

Inoltre, dobbiamo consentire a Unity di aggiornare la vista del progetto e i riferimenti ai file; per farlo dobbiamo chiamare AssetDatabase.Refresh ().

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

Proviamo a verificare se la texture viene creata quando eseguiamo la nostra routine.


Passaggio 9: creare un materiale

Abbiamo un'immagine e ora possiamo creare un materiale che lo utilizza come una trama. Creiamo a nuovo materiale.

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

Il materiale creato utilizzerà a Diffondere shader. Per salvare questo materiale nel file, possiamo chiamare AssetDatabase.CreateAsset (). Questa funzione accetta una risorsa come primo argomento e il percorso come seconda.

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

Se esegui la nostra routine ora, vedrai che il materiale è stato creato.

Come puoi vedere tutto è corretto, il suo nome è Nuovo materiale e usa Diffondere shader, ma non vi è alcuna texture assegnata.


Passaggio 10: Assegna la trama

Per prima cosa dobbiamo ottenere un riferimento al materiale che abbiamo appena creato. Possiamo ottenerlo chiamando AssetDatabase.LoadAssetAtPath () che carica l'asset e restituisce il suo riferimento.

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

Ora assegniamo la texture generata come trama principale del materiale. Possiamo ottenere il riferimento di trama della trama generata nello stesso modo in cui abbiamo ottenuto il riferimento materiale.

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

Per vedere i risultati, eseguire il Routine materiale.

Come puoi vedere, il materiale ha la texture assegnata ora.

Conclusione

Questa è la fine dell'introduzione per gestire le tue risorse usando gli script. Se si desidera espandere la propria conoscenza sull'argomento, è possibile visitare la pagina di riferimento delle Classi di Unity Editor, in particolare vale la pena esaminare il riferimento allo script AssetDatabase. Se hai bisogno di lavorare a un livello basso, dovresti anche leggere i documenti su System.IO per ottenere maggiori informazioni sulle sue classi e su come puoi usarle. Grazie per il tuo tempo!