unity3d
Importörer och (post) processorer
Sök…
Syntax
- AssetPostprocessor.OnPreprocessTexture ()
Anmärkningar
Använd String.Contains()
att bara bearbeta tillgångar som har en given sträng i sina tillgångsvägar.
if (assetPath.Contains("ProcessThisFolder"))
{
// Process asset
}
Textur postprocessor
Skapa TexturePostProcessor.cs
fil var som helst i mappen Tillgångar :
using UnityEngine;
using UnityEditor;
public class TexturePostProcessor : AssetPostprocessor
{
void OnPostprocessTexture(Texture2D texture)
{
TextureImporter importer = assetImporter as TextureImporter;
importer.anisoLevel = 1;
importer.filterMode = FilterMode.Bilinear;
importer.mipmapEnabled = true;
importer.npotScale = TextureImporterNPOTScale.ToLarger;
importer.textureType = TextureImporterType.Advanced;
}
}
Nu, varje gång Unity importerar en struktur kommer den att ha följande parametrar:
Om du använder postprocessor kan du inte ändra texturparametrar genom att manipulera Importinställningar i redigeraren.
När du trycker på Apply- knappen importeras strukturen och postprocessorkoden körs igen.
En grundläggande importör
Antag att du har en anpassad fil du vill skapa en importör för. Det kan vara en .xls-fil eller vad som helst. I det här fallet kommer vi att använda en JSON-fil eftersom det är enkelt men vi kommer att välja ett anpassat tillägg för att göra det enkelt att säga vilka filer som är våra?
Låt oss anta att formatet för JSON-filen är
{
"someValue": 123,
"someOtherValue": 456.297,
"someBoolValue": true,
"someStringValue": "this is a string",
}
Låt oss spara det som Example.test
någonstans utanför tillgångarna för tillfället.
MonoBehaviour
en MonoBehaviour
med en anpassad klass bara för data. Den anpassade klassen är enbart för att göra det enkelt att deserialisera JSON. Du behöver INTE använda en anpassad klass men det gör detta exempel kortare. Vi sparar detta i TestData.cs
using UnityEngine;
using System.Collections;
public class TestData : MonoBehaviour {
[System.Serializable]
public class Data {
public int someValue = 0;
public float someOtherValue = 0.0f;
public bool someBoolValue = false;
public string someStringValue = "";
}
public Data data = new Data();
}
Om du manuellt skulle lägga till det skriptet till ett GameObject skulle du se något liknande
Skapa sedan en Editor
mapp någonstans under Assets
. Jag kan vara på vilken nivå som helst. Inuti Editor-mappen gör du en TestDataAssetPostprocessor.cs
fil och lägg den i den.
using UnityEditor;
using UnityEngine;
using System.Collections;
public class TestDataAssetPostprocessor : AssetPostprocessor
{
const string s_extension = ".test";
// NOTE: Paths start with "Assets/"
static bool IsFileWeCareAbout(string path)
{
return System.IO.Path.GetExtension(path).Equals(
s_extension,
System.StringComparison.Ordinal);
}
static void HandleAddedOrChangedFile(string path)
{
string text = System.IO.File.ReadAllText(path);
// should we check for error if the file can't be parsed?
TestData.Data newData = JsonUtility.FromJson<TestData.Data>(text);
string prefabPath = path + ".prefab";
// Get the existing prefab
GameObject existingPrefab =
AssetDatabase.LoadAssetAtPath(prefabPath, typeof(Object)) as GameObject;
if (!existingPrefab)
{
// If no prefab exists make one
GameObject newGameObject = new GameObject();
newGameObject.AddComponent<TestData>();
PrefabUtility.CreatePrefab(prefabPath,
newGameObject,
ReplacePrefabOptions.Default);
GameObject.DestroyImmediate(newGameObject);
existingPrefab =
AssetDatabase.LoadAssetAtPath(prefabPath, typeof(Object)) as GameObject;
}
TestData testData = existingPrefab.GetComponent<TestData>();
if (testData != null)
{
testData.data = newData;
EditorUtility.SetDirty(existingPrefab);
}
}
static void HandleRemovedFile(string path)
{
// Decide what you want to do here. If the source file is removed
// do you want to delete the prefab? Maybe ask if you'd like to
// remove the prefab?
// NOTE: Because you might get many calls (like you deleted a
// subfolder full of .test files you might want to get all the
// filenames and ask all at once ("delete all these prefabs?").
}
static void OnPostprocessAllAssets (string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
foreach (var path in importedAssets)
{
if (IsFileWeCareAbout(path))
{
HandleAddedOrChangedFile(path);
}
}
foreach (var path in deletedAssets)
{
if (IsFileWeCareAbout(path))
{
HandleRemovedFile(path);
}
}
for (var ii = 0; ii < movedAssets.Length; ++ii)
{
string srcStr = movedFromAssetPaths[ii];
string dstStr = movedAssets[ii];
// the source was moved, let's move the corresponding prefab
// NOTE: We don't handle the case if there already being
// a prefab of the same name at the destination
string srcPrefabPath = srcStr + ".prefab";
string dstPrefabPath = dstStr + ".prefab";
AssetDatabase.MoveAsset(srcPrefabPath, dstPrefabPath);
}
}
}
Med det sparade bör du kunna dra och släppa Example.test
filen som vi skapade ovan i mappen Unity Assets och du bör se motsvarande prefab skapat. Om du redigerar Example.test
ser du Example.test
uppdateras omedelbart. Om du drar prefaben in i scenhierarkin ser du den uppdateras såväl som Example.test
. Om du flyttar Example.test
till en annan mapp flyttas motsvarande prefab med den. Om du ändrar ett fält i en instans ändrar Example.test
filen Example.test
ser du bara de fält som du inte har ändrat på instansen uppdateras.
Förbättringar: I exemplet ovan, efter att du har Example.test
till mappen Assets
ser du att det finns både ett Example.test
och ett Example.test.prefab
. Det skulle vara bra att veta att det fungerar mer som modellimportörerna fungerar, vi skulle bara se Example.test
och det är en AssetBundle
eller något sådant. Om du vet hur du kan ge det exemplet