В продолжении темы. Если имеем толстый проект, с большим количеством элементов в project(в моем случае около 7000), получаем при выборе атласа длительный парсинг проекта. Дабы избежать этого нужно каким то образом индексировать атласы. Данное решение работает только в контексте индексации самих атласов и ничего более.
Ищем класс dfTextureAtlasInspector, в любом месте добавляем
Используется csharp
private static string tempPath;
[MenuItem("Tools/Daikon Forge/Texture Atlas/Rebuild Atlas Index")]
public static void RebuildIndex()
{
var collection = new List<GameObject>();
var progressTime = Environment.TickCount;
var allAssetPaths = AssetDatabase.GetAllAssetPaths();
for (int i = 0; i < allAssetPaths.Length; i++)
{
if (Environment.TickCount - progressTime > 250)
{
progressTime = Environment.TickCount;
EditorUtility.DisplayProgressBar("Build Index", "Loading prefabs", (float)i / (float)allAssetPaths.Length);
}
var path = allAssetPaths[i];
if (!path.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
continue;
try
{
var go = AssetDatabase.LoadMainAssetAtPath(path) as GameObject;
if (IsPrefab(go))
{
if (go.GetComponent<dfAtlas>() != null)
{
collection.Add(go);
}
}
go = null;
EditorUtility.UnloadUnusedAssets();
}
catch (Exception err)
{
Debug.LogError("Error loading prefab at " + path + " - " + err.Message);
}
}
EditorUtility.ClearProgressBar();
dfIndexLogic logic = new dfIndexLogic();
logic.SaveIndex(collection);
}
private static bool IsPrefab(GameObject item)
{
try
{
return
item != null &&
PrefabUtility.GetPrefabParent(item) == null &&
PrefabUtility.GetPrefabObject(item) != null;
}
catch
{
return false;
}
}
Ищем в нем в CreateAtlasFromSelection(). После
Используется csharp
finally
{
EditorUtility.ClearProgressBar();
}
Добавляем
Используется csharp
dfIndexLogic logic = new dfIndexLogic();
var addableAtlas = AssetDatabase.LoadMainAssetAtPath(tempPath) as GameObject;
logic.AddAtlas((GameObject)addableAtlas);
addableAtlas = null;
Ищем класс dfPrefabSelectionDialog. Ищем метод getFilteredItems(). Заменяем его на
Используется csharp
private List<GameObject> getFilteredItems()
{
if (allAtlasInProject == null)
{
allAtlasInProject = new List<GameObject>();
dfIndexLogic indexLogic = new dfIndexLogic();
var _atlasIndex = indexLogic.GetIndex();
if (_atlasIndex != null)
{
if (_atlasIndex.Atlases.Count > 0)
{
foreach (var atlas in _atlasIndex.Atlases)
{
if (atlas != null)
{
allAtlasInProject.Add(atlas);
}
else
{
allAtlasInProject.Clear();
IniAtlasInProject(indexLogic);
break;
}
}
}
else
{
IniAtlasInProject(indexLogic);
}
}
else
{
IniAtlasInProject(indexLogic);
}
indexLogic = null;
}
return allAtlasInProject;
}
Также добавляем методы
Используется csharp
void IniAtlasInProject(dfIndexLogic _logic)
{
allAtlasInProject = GetAtlasCollection();
_logic.SaveIndex(allAtlasInProject);
}
private List<GameObject> GetAtlasCollection()
{
var collection= new List<GameObject>();
var progressTime = Environment.TickCount;
var allAssetPaths = AssetDatabase.GetAllAssetPaths();
for( int i = 0; i < allAssetPaths.Length; i++ )
{
if( Environment.TickCount - progressTime > 250 )
{
progressTime = Environment.TickCount;
EditorUtility.DisplayProgressBar( this.title, "Loading prefabs", (float)i / (float)allAssetPaths.Length );
}
var path = allAssetPaths[ i ];
if( !path.EndsWith( ".prefab", StringComparison.OrdinalIgnoreCase ) )
continue;
try
{
var go = AssetDatabase.LoadMainAssetAtPath( path ) as GameObject;
if (IsPrefab(go))
{
if (go.GetComponent(componentType) != null)
{
try
{
if (filterCallback != null && !filterCallback(go))
continue;
}
catch { continue; }
if (go.name.IndexOf(searchFilter, StringComparison.OrdinalIgnoreCase) != -1)
{
collection.Add(go);
}
}
}
go = null;
EditorUtility.UnloadUnusedAssets();
}
catch( Exception err )
{
Debug.LogError( "Error loading prefab at " + path + " - " + err.Message );
}
}
EditorUtility.ClearProgressBar();
return collection;
}
Создаем класс
Используется csharp
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class dfIndexLogic
{
public const string indexPath = "Assets/_dfIndex.asset";
public dfAtlasIndex GetIndex()
{
return Resources.LoadAssetAtPath(indexPath, typeof(dfAtlasIndex)) as dfAtlasIndex;
}
public void SaveIndex(List<GameObject> _collection)
{
if (_collection.Count > 0)
{
dfAtlasIndex newIndex = ScriptableObject.CreateInstance<dfAtlasIndex>();
Sort(_collection);
foreach (var atlas in _collection)
{
newIndex.Atlases.Add(atlas);
}
AssetDatabase.CreateAsset(newIndex, dfIndexLogic.indexPath);
AssetDatabase.SaveAssets();
}
else BuildIndex();
}
void BuildIndex()
{
dfAtlasIndex newIndex = ScriptableObject.CreateInstance<dfAtlasIndex>();
AssetDatabase.CreateAsset(newIndex, dfIndexLogic.indexPath);
AssetDatabase.SaveAssets();
}
void Sort(List<GameObject> _collection)
{
_collection.Sort((GameObject lhs, GameObject rhs) =>
{
return lhs.name.CompareTo(rhs.name);
});
}
public void AddAtlas(GameObject _atlas)
{
var index = GetIndex();
if (index == null)
{
BuildIndex();
index = GetIndex();
}
var collection = index.Atlases;
collection.Add(_atlas);
SaveIndex(collection);
}
}
Создаем класс индекса
Используется csharp
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class dfAtlasIndex : ScriptableObject
{
public List<GameObject> Atlases = new List<GameObject>();
}
Перед началом использования в уже рабочем проекте, если есть созданные атласы, создать индекс- Tools/ Daikon Forge/ Texture Atlas/ Rebuild Atlas Index. Все ваши атласы хранятся в _dfIndex.asset. Если вы удалите атлас из проекта, при последующем обращении к атласам индекс будет обновлен. Если ручками начнете править индекс, инициализировать корректный индекс можно через его ребилд.