improved handling of Reimport All and some other weird asset import cases

This commit is contained in:
Serhii Yolkin 2015-10-11 20:26:42 +02:00
parent aa4a8d08e6
commit 7d60e4e255
6 changed files with 104 additions and 5 deletions

View File

@ -0,0 +1,21 @@
using UnityEngine;
namespace Spine {
public static class AssetDatabaseAvailabilityDetector {
const string MARKER_RESOURCE_NAME = "SpineAssetDatabaseMarker";
private static bool _isMarkerLoaded;
public static bool IsAssetDatabaseAvailable (bool forceCheck = false) {
if (!forceCheck && _isMarkerLoaded)
return true;
TextAsset markerTextAsset = Resources.Load<TextAsset>(MARKER_RESOURCE_NAME);
_isMarkerLoaded = markerTextAsset != null;
if (markerTextAsset != null) {
Resources.UnloadAsset(markerTextAsset);
}
return _isMarkerLoaded;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 25086cd81e3158b439761b73d7366c47
timeCreated: 1444587791
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 24903fdac57ee784b9597fcb751ec22f
folderAsset: yes
timeCreated: 1444565388
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1 @@
DO NOT MOVE OR DELETE THIS FILE

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 57281c00bdd90ad4392f811f2b9f0da1
timeCreated: 1444565392
licenseType: Pro
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -149,6 +149,7 @@ public class SpineEditorUtilities : AssetPostprocessor {
public static string editorPath = "";
public static string editorGUIPath = "";
static HashSet<string> assetsImportedInWrongState;
static Dictionary<int, GameObject> skeletonRendererTable;
static Dictionary<int, SkeletonUtilityBone> skeletonUtilityBoneTable;
static Dictionary<int, BoundingBoxFollower> boundingBoxFollowerTable;
@ -173,6 +174,7 @@ public class SpineEditorUtilities : AssetPostprocessor {
Icons.Initialize();
assetsImportedInWrongState = new HashSet<string>();
skeletonRendererTable = new Dictionary<int, GameObject>();
skeletonUtilityBoneTable = new Dictionary<int, SkeletonUtilityBone>();
boundingBoxFollowerTable = new Dictionary<int, BoundingBoxFollower>();
@ -254,8 +256,34 @@ public class SpineEditorUtilities : AssetPostprocessor {
}
static void OnPostprocessAllAssets (string[] imported, string[] deleted, string[] moved, string[] movedFromAssetPaths) {
ImportSpineContent(imported, false);
if (imported.Length == 0)
return;
// In case user used "Assets -> Reimport All", during the import process,
// asset database is not initialized until some point. During that period,
// all attempts to load any assets using API (i.e. AssetDatabase.LoadAssetAtPath)
// will return null, and as result, assets won't be loaded even if they actually exists,
// which may lead to numerous importing errors.
// This situation also happens if Library folder is deleted from the project, which is a pretty
// common case, since when using version control systems, the Library folder must be excluded.
//
// So to avoid this, in case asset database is not available, we delay loading the assets
// until next time.
//
// Unity *always* reimports some internal assets after the process is done, so this method
// is always called once again in a state when asset database is available.
//
// Checking whether AssetDatabase is initialized is done by attempting to load
// a known "marker" asset that should always be available. Failing to load this asset
// means that AssetDatabase is not initialized.
assetsImportedInWrongState.UnionWith(imported);
if (AssetDatabaseAvailabilityDetector.IsAssetDatabaseAvailable()) {
string[] combinedAssets = assetsImportedInWrongState.ToArray();
assetsImportedInWrongState.Clear();
ImportSpineContent(combinedAssets);
}
}
public static void ImportSpineContent (string[] imported, bool reimport = false) {
List<string> atlasPaths = new List<string>();
List<string> imagePaths = new List<string>();
@ -408,14 +436,34 @@ public class SpineEditorUtilities : AssetPostprocessor {
skeletonDataAsset.Reset();
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(skeletonDataAsset));
string lastHash = EditorPrefs.GetString(guid + "_hash");
if (lastHash != skeletonDataAsset.GetSkeletonData(true).Hash) {
string lastHash = EditorPrefs.GetString(guid + "_hash");
// For some weird reason sometimes Unity loses the internal Object pointer,
// and as a result, all comparisons with null returns true.
// But the C# wrapper is still alive, so we can "restore" the object
// by reloading it from its Instance ID.
AtlasAsset[] skeletonDataAtlasAssets = skeletonDataAsset.atlasAssets;
if (skeletonDataAtlasAssets != null) {
for (int i = 0; i < skeletonDataAtlasAssets.Length; i++) {
if (!ReferenceEquals(null, skeletonDataAtlasAssets[i]) &&
skeletonDataAtlasAssets[i].Equals(null) &&
skeletonDataAtlasAssets[i].GetInstanceID() != 0
) {
skeletonDataAtlasAssets[i] = EditorUtility.InstanceIDToObject(skeletonDataAtlasAssets[i].GetInstanceID()) as AtlasAsset;
}
}
}
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
string currentHash = skeletonData != null ? skeletonData.Hash : null;
if (currentHash == null || lastHash != currentHash) {
//do any upkeep on synchronized assets
UpdateMecanimClips(skeletonDataAsset);
}
EditorPrefs.SetString(guid + "_hash", skeletonDataAsset.GetSkeletonData(true).Hash);
if (currentHash != null) {
EditorPrefs.SetString(guid + "_hash", currentHash);
}
}
}
}