我将一些自动生成的数据导出到我的Unity项目中。为了帮助我,我想为这些资产分配一个自定义图标,以便清楚地识别它们。这当然可以通过编辑器本身实现,但理想情况下我希望在导入时自动发生。
为此,我编写了一个AssetPostProcessor,它应该为我解决这个问题。在下面的示例中(适用于MonoScripts作为示例,但可以应用于任何类型的资产),所有新导入的脚本都将分配MyFancyIcon图标。此更新在脚本资产本身以及检查器中的MonoBehaviours上都可见。
using UnityEngine;
using UnityEditor;
using System.Reflection;
public class IconAssignmentPostProcessor : AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
Texture2D icon = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Iconfolder/MyFancyIcon.png");
foreach (string asset in importedAssets)
{
MonoScript script = AssetDatabase.LoadAssetAtPath<MonoScript>(asset);
if(script != null)
{
PropertyInfo inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
SerializedObject serializedObject = new SerializedObject(script);
inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);
SerializedProperty iconProperty = serializedObject.FindProperty("m_Icon");
iconProperty.objectReferenceValue = icon;
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
EditorUtility.SetDirty(script);
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
除了一个问题外,它的工作正常。关闭项目并重新打开时,不会保存更新。据我所知,EditorUtility.SetDirty(script);
电话应该处理此问题,或者至少是AssetDatabase.SaveAssets();
电话。
但是,查看手动分配图标(有效)和以编程方式进行操作之间的区别,在与手动分配图标时设置的资产关联的元文件中有一个icon
字段,但不是在我的脚本案例中。 (在脚本化的情况下,元文件甚至没有更新)
那是什么给出的?当我(显然)只有元数据发生变化时,我是否必须做任何特别的事情?我有什么简单的俯视吗?
答案 0 :(得分:5)
使用此代码进行实验并得出结论,这是一个错误。与Unity联系,这是他们的答复:
目前,它是一个提交的错误,我们的开发人员团队是 调查它。似乎这个错误似乎是因为 AssetDatabes.SaveAssets()不保存更改。
解决方法是手动执行此操作。
调用OnPostprocessAllAssets时处理和保存数据:
1 。创建一个Json文件设置,如果它不存在,将保存设置。
2 。调用OnPostprocessAllAssets
时,加载旧的Json文件设置。
4 。在资产上添加花哨的图标。
5 。覆盖已加载的Json文件设置,并检查它是否包含importedAssets
参数中的文件。
如果它包含已加载的文件,请修改该设置并保存。如果没有,请将其添加到列表中然后保存。
6 。检查具有importedAssets
的硬盘驱动器上的资产File.Exists
是否存在。如果它不存在,请将其从加载的Json文件设置列表中删除,然后保存。
Unity加载时自动重新应用精美图标:
1 。向IconAssignmentPostProcessor
类添加静态构造函数。当加载编辑器时以及调用OnPostprocessAllAssets
时,将自动调用此静态构造函数。
2 。当调用构造函数时,创建一个Json文件设置,如果它不存在,将保存设置。
3 。加载旧的Json文件设置。
4 。通过循环加载的Json文件重新应用花哨的图标。
5 。检查加载的Json文件是否仍有资源不在驱动器上。如果是,请从列表中删除该资产,然后保存。
以下是新IconAssignmentPostProcessor
脚本的外观:
using UnityEngine;
using UnityEditor;
using System.Reflection;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System;
public class IconAssignmentPostProcessor : AssetPostprocessor
{
// Called when Editor Starts
static IconAssignmentPostProcessor()
{
prepareSettingsDir();
reloadAllFancyIcons();
}
private static string settingsPath = Application.dataPath + "/FancyIconSettings.text";
private static string fancyIconPath = "Assets/Iconfolder/MyFancyIcon.png";
private static bool firstRun = true;
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
prepareSettingsDir();
//Load old settings
FancyIconSaver savedFancyIconSaver = LoadSettings();
Texture2D icon = AssetDatabase.LoadAssetAtPath<Texture2D>(fancyIconPath);
for (int j = 0; j < importedAssets.Length; j++)
{
string asset = importedAssets[j];
MonoScript script = AssetDatabase.LoadAssetAtPath<MonoScript>(asset);
if (script != null)
{
//Apply fancy Icon
ApplyIcon(script, icon);
//Process each asset
processFancyIcon(savedFancyIconSaver, fancyIconPath, asset, pathToGUID(asset));
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
public static string pathToGUID(string path)
{
return AssetDatabase.AssetPathToGUID(path);
}
public static string guidToPath(string guid)
{
return AssetDatabase.GUIDToAssetPath(guid);
}
public static void processFancyIcon(FancyIconSaver oldSettings, string fancyIconPath, string scriptPath, string scriptGUID)
{
int matchIndex = -1;
if (oldSettings == null)
{
oldSettings = new FancyIconSaver();
}
if (oldSettings.fancyIconData == null)
{
oldSettings.fancyIconData = new List<FancyIconData>();
}
FancyIconData fancyIconData = new FancyIconData();
fancyIconData.fancyIconPath = fancyIconPath;
fancyIconData.scriptPath = scriptPath;
fancyIconData.scriptGUID = scriptGUID;
//Check if this guid exist in the List already. If so, override it with the match index
if (containsGUID(oldSettings, scriptGUID, out matchIndex))
{
oldSettings.fancyIconData[matchIndex] = fancyIconData;
}
else
{
//Does not exist, add it to the existing one
oldSettings.fancyIconData.Add(fancyIconData);
}
//Save the data
SaveSettings(oldSettings);
//If asset does not exist, delete it from the json settings
for (int i = 0; i < oldSettings.fancyIconData.Count; i++)
{
if (!assetExist(scriptPath))
{
//Remove it from the List then save the modified List
oldSettings.fancyIconData.RemoveAt(i);
SaveSettings(oldSettings);
Debug.Log("Asset " + scriptPath + " no longer exist. Deleted it from JSON Settings");
continue; //Continue to the next Settings in the List
}
}
}
//Re-loads all the fancy icons
public static void reloadAllFancyIcons()
{
if (!firstRun)
{
firstRun = false;
return; //Exit if this is not first run
}
//Load old settings
FancyIconSaver savedFancyIconSaver = LoadSettings();
if (savedFancyIconSaver == null || savedFancyIconSaver.fancyIconData == null)
{
Debug.Log("No Previous Fancy Icon Settings Found!");
return;//Exit
}
//Apply Icon Changes
for (int i = 0; i < savedFancyIconSaver.fancyIconData.Count; i++)
{
string asset = savedFancyIconSaver.fancyIconData[i].scriptPath;
//If asset does not exist, delete it from the json settings
if (!assetExist(asset))
{
//Remove it from the List then save the modified List
savedFancyIconSaver.fancyIconData.RemoveAt(i);
SaveSettings(savedFancyIconSaver);
Debug.Log("Asset " + asset + " no longer exist. Deleted it from JSON Settings");
continue; //Continue to the next Settings in the List
}
string tempFancyIconPath = savedFancyIconSaver.fancyIconData[i].fancyIconPath;
Texture2D icon = AssetDatabase.LoadAssetAtPath<Texture2D>(tempFancyIconPath);
MonoScript script = AssetDatabase.LoadAssetAtPath<MonoScript>(asset);
if (script == null)
{
continue;
}
Debug.Log(asset);
ApplyIcon(script, icon);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void ApplyIcon(MonoScript script, Texture2D icon)
{
PropertyInfo inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
SerializedObject serializedObject = new SerializedObject(script);
inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);
SerializedProperty iconProperty = serializedObject.FindProperty("m_Icon");
iconProperty.objectReferenceValue = icon;
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
EditorUtility.SetDirty(script);
Debug.Log("Applied Fancy Icon to: " + script.name);
}
//Creates the Settings File if it does not exit yet
private static void prepareSettingsDir()
{
if (!File.Exists(settingsPath))
{
File.Create(settingsPath);
}
}
public static void SaveSettings(FancyIconSaver fancyIconSaver)
{
try
{
string jsonData = JsonUtility.ToJson(fancyIconSaver, true);
Debug.Log("Data: " + jsonData);
byte[] jsonByte = Encoding.ASCII.GetBytes(jsonData);
File.WriteAllBytes(settingsPath, jsonByte);
}
catch (Exception e)
{
Debug.Log("Settings not Saved: " + e.Message);
}
}
public static FancyIconSaver LoadSettings()
{
FancyIconSaver loadedData = null;
try
{
byte[] jsonByte = File.ReadAllBytes(settingsPath);
string jsonData = Encoding.ASCII.GetString(jsonByte);
loadedData = JsonUtility.FromJson<FancyIconSaver>(jsonData);
return loadedData;
}
catch (Exception e)
{
Debug.Log("No Settings Loaded: " + e.Message);
}
return loadedData;
}
public static bool containsGUID(FancyIconSaver fancyIconSaver, string guid, out int matchIndex)
{
matchIndex = -1;
if (fancyIconSaver == null || fancyIconSaver.fancyIconData == null)
{
Debug.Log("List is null");
return false;
}
for (int i = 0; i < fancyIconSaver.fancyIconData.Count; i++)
{
if (fancyIconSaver.fancyIconData[i].scriptGUID == guid)
{
matchIndex = i;
return true;
}
}
return false;
}
public static bool assetExist(string path)
{
return File.Exists(path);
}
[Serializable]
public class FancyIconSaver
{
public List<FancyIconData> fancyIconData;
}
[Serializable]
public class FancyIconData
{
public string fancyIconPath;
public string scriptPath;
public string scriptGUID;
}
}
重启Unity时,这应该包含花哨的图标。
答案 1 :(得分:0)