unity3d
Importerzy i (post) przetwórcy
Szukaj…
Składnia
- AssetPostprocessor.OnPreprocessTexture ()
Uwagi
Użyj String.Contains()
do przetwarzania tylko zasobów, które mają podany ciąg w ścieżkach zasobów.
if (assetPath.Contains("ProcessThisFolder"))
{
// Process asset
}
Postprocesor tekstury
Utwórz plik TexturePostProcessor.cs
w dowolnym miejscu w folderze zasobów :
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;
}
}
Teraz za każdym razem, gdy Unity importuje teksturę, będzie mieć następujące parametry:
Jeśli używasz postprocesora, nie możesz zmieniać parametrów tekstury, manipulując ustawieniami importu w edytorze.
Po naciśnięciu przycisku Zastosuj tekstura zostanie ponownie zaimportowana, a kod postprocesora zostanie ponownie uruchomiony.
Podstawowy importer
Załóżmy, że masz plik niestandardowy, dla którego chcesz utworzyć importera. Może to być plik .xls lub cokolwiek innego. W takim przypadku użyjemy pliku JSON, ponieważ jest to łatwe, ale wybieramy niestandardowe rozszerzenie, aby ułatwić określenie, które pliki są nasze?
Załóżmy, że format pliku JSON to
{
"someValue": 123,
"someOtherValue": 456.297,
"someBoolValue": true,
"someStringValue": "this is a string",
}
Zachowajmy to na razie. Example.test
gdzieś poza zasobami.
Następnie utwórz MonoBehaviour
z niestandardową klasą tylko dla danych. Klasa niestandardowa służy wyłącznie ułatwieniu deserializacji JSON. NIE musisz używać niestandardowej klasy, ale to skraca ten przykład. TestData.cs
to w 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();
}
Jeśli ręcznie dodasz ten skrypt do GameObject, zobaczysz coś takiego
Następnie utwórz folder Editor
gdzieś w obszarze Assets
. Mogę być na dowolnym poziomie. W folderze Editor utwórz plik TestDataAssetPostprocessor.cs
i umieść go w nim.
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);
}
}
}
Po tym zapisaniu powinieneś być w stanie przeciągnąć i upuścić Example.test
, który utworzyliśmy powyżej, do folderu Unity Assets i powinieneś zobaczyć odpowiedni prefabrykat utworzony. Jeśli edytujesz Example.test
, zobaczysz, że dane w prefabrykacie są natychmiast aktualizowane. Jeśli przeciągniesz prefabrykat do hierarchii scen, zobaczysz, że jest aktualizowany, a także zmiany w przykładzie. Example.test
. Jeśli przeniesiesz Example.test
do innego folderu, przeniesie się z nim odpowiedni prefabrykat. Jeśli zmienisz pole w instancji, a następnie zmienisz Example.test
, zobaczysz tylko pola, których nie zmodyfikowałeś w instancji.
Ulepszenia: W powyższym przykładzie po przeciągnięciu Example.test
do folderu Assets
zobaczysz, że istnieje zarówno Example.test
i Example.test.prefab
. Byłoby wspaniale wiedzieć, aby działało to tak, jak działają importerzy modeli, w magiczny sposób zobaczylibyśmy tylko Example.test
i jest to AssetBundle
lub coś takiego. Jeśli wiesz, jak podać ten przykład