[unity] On-demand loading of Atlas Textures now supports SkeletonGraphic. Added method RequestLoadTexture and TextureRequested delegate to OnDemandTextureLoader. Fixed missing loader asset name suffix. See #1890.

This commit is contained in:
Harald Csaszar 2023-10-06 18:32:09 +02:00
parent f5caeacf0c
commit 8bc1201b83
10 changed files with 161 additions and 26 deletions

View File

@ -71,6 +71,11 @@ namespace Spine.Unity {
onDemandTextureLoader.RequestLoadMaterialTextures(material, ref overrideMaterial); onDemandTextureLoader.RequestLoadMaterialTextures(material, ref overrideMaterial);
} }
public virtual void RequireTextureLoaded (Texture placeholderTexture, ref Texture replacementTexture, System.Action<Texture> onTextureLoaded) {
if (onDemandTextureLoader)
onDemandTextureLoader.RequestLoadTexture(placeholderTexture, ref replacementTexture, onTextureLoaded);
}
[SerializeField] protected LoadingMode textureLoadingMode = LoadingMode.Normal; [SerializeField] protected LoadingMode textureLoadingMode = LoadingMode.Normal;
[SerializeField] protected OnDemandTextureLoader onDemandTextureLoader = null; [SerializeField] protected OnDemandTextureLoader onDemandTextureLoader = null;
#endif #endif

View File

@ -51,6 +51,27 @@ namespace Spine.Unity {
/// <param name="placeholderMaterials">A newly created list of materials which has a placeholder texture assigned.</param> /// <param name="placeholderMaterials">A newly created list of materials which has a placeholder texture assigned.</param>
/// <returns>True, if any placeholder texture is assigned at a Material of the associated AtlasAssetBase.</returns> /// <returns>True, if any placeholder texture is assigned at a Material of the associated AtlasAssetBase.</returns>
public abstract bool HasPlaceholderTexturesAssigned (out List<Material> placeholderMaterials); public abstract bool HasPlaceholderTexturesAssigned (out List<Material> placeholderMaterials);
/// <summary>
/// Returns whether any main texture is null at a Material of the associated AtlasAssetBase.
/// </summary>
/// <param name="nullTextureMaterials">A newly created list of materials which has a null main texture assigned.</param>
/// <returns>True, if any null main texture is assigned at a Material of the associated AtlasAssetBase.</returns>
public virtual bool HasNullMainTexturesAssigned (out List<Material> nullTextureMaterials) {
nullTextureMaterials = null;
if (!atlasAsset) return false;
bool anyNullTexture = false;
foreach (Material material in atlasAsset.Materials) {
if (material.mainTexture == null) {
anyNullTexture = true;
if (nullTextureMaterials == null) nullTextureMaterials = new List<Material>();
nullTextureMaterials.Add(material);
}
}
return anyNullTexture;
}
/// <summary> /// <summary>
/// Assigns previously setup target textures at each Material where placeholder textures are setup.</summary> /// Assigns previously setup target textures at each Material where placeholder textures are setup.</summary>
/// <returns>True on success, false if the target texture could not be assigned at any of the /// <returns>True on success, false if the target texture could not be assigned at any of the
@ -60,13 +81,20 @@ namespace Spine.Unity {
public abstract void EndCustomTextureLoading (); public abstract void EndCustomTextureLoading ();
public abstract bool HasPlaceholderAssigned (Material material); public abstract bool HasPlaceholderAssigned (Material material);
public abstract void RequestLoadMaterialTextures (Material material, ref Material overrideMaterial); public abstract void RequestLoadMaterialTextures (Material material, ref Material overrideMaterial);
public abstract void RequestLoadTexture (Texture placeholderTexture, ref Texture replacementTexture,
System.Action<Texture> onTextureLoaded = null);
public abstract void Clear (bool clearAtlasAsset = false); public abstract void Clear (bool clearAtlasAsset = false);
#region Event delegates #region Event delegates
public delegate void TextureLoadDelegate (OnDemandTextureLoader loader, Material material, int textureIndex); public delegate void TextureLoadDelegate (OnDemandTextureLoader loader, Material material, int textureIndex);
protected event TextureLoadDelegate onTextureRequested;
protected event TextureLoadDelegate onTextureLoaded; protected event TextureLoadDelegate onTextureLoaded;
protected event TextureLoadDelegate onTextureUnloaded; protected event TextureLoadDelegate onTextureUnloaded;
public event TextureLoadDelegate TextureRequested {
add { onTextureRequested += value; }
remove { onTextureRequested -= value; }
}
public event TextureLoadDelegate TextureLoaded { public event TextureLoadDelegate TextureLoaded {
add { onTextureLoaded += value; } add { onTextureLoaded += value; }
remove { onTextureLoaded -= value; } remove { onTextureLoaded -= value; }
@ -76,6 +104,10 @@ namespace Spine.Unity {
remove { onTextureUnloaded -= value; } remove { onTextureUnloaded -= value; }
} }
protected void OnTextureRequested (Material material, int textureIndex) {
if (onTextureRequested != null)
onTextureRequested(this, material, textureIndex);
}
protected void OnTextureLoaded (Material material, int textureIndex) { protected void OnTextureLoaded (Material material, int textureIndex) {
if (onTextureLoaded != null) if (onTextureLoaded != null)
onTextureLoaded(this, material, textureIndex); onTextureLoaded(this, material, textureIndex);

View File

@ -35,6 +35,8 @@
#define HAS_CULL_TRANSPARENT_MESH #define HAS_CULL_TRANSPARENT_MESH
#endif #endif
#define SPINE_OPTIONAL_ON_DEMAND_LOADING
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
@ -821,15 +823,23 @@ namespace Spine.Unity {
else else
canvasRenderer.SetMesh(null); canvasRenderer.SetMesh(null);
bool assignTexture = false;
if (currentInstructions.submeshInstructions.Count > 0) { if (currentInstructions.submeshInstructions.Count > 0) {
Material material = currentInstructions.submeshInstructions.Items[0].material; Material material = currentInstructions.submeshInstructions.Items[0].material;
if (material != null && baseTexture != material.mainTexture) { if (material != null && baseTexture != material.mainTexture) {
baseTexture = material.mainTexture; baseTexture = material.mainTexture;
if (overrideTexture == null && assignAtCanvasRenderer) if (overrideTexture == null && assignAtCanvasRenderer)
assignTexture = true;
}
}
#if SPINE_OPTIONAL_ON_DEMAND_LOADING
if (Application.isPlaying)
HandleOnDemandLoading();
#endif
if (assignTexture)
canvasRenderer.SetTexture(this.mainTexture); canvasRenderer.SetTexture(this.mainTexture);
} }
}
}
protected void UpdateMaterialsMultipleCanvasRenderers (SkeletonRendererInstruction currentInstructions) { protected void UpdateMaterialsMultipleCanvasRenderers (SkeletonRendererInstruction currentInstructions) {
int submeshCount = currentInstructions.submeshInstructions.Count; int submeshCount = currentInstructions.submeshInstructions.Count;
@ -899,7 +909,6 @@ namespace Spine.Unity {
bool pmaVertexColors = meshGenerator.settings.pmaVertexColors; bool pmaVertexColors = meshGenerator.settings.pmaVertexColors;
Material[] usedMaterialItems = usedMaterials.Items; Material[] usedMaterialItems = usedMaterials.Items;
Texture[] usedTextureItems = usedTextures.Items; Texture[] usedTextureItems = usedTextures.Items;
bool assignAtCanvasRenderer = (assignMeshOverrideSingle == null || !disableMeshAssignmentOnOverride);
for (int i = 0; i < submeshCount; i++) { for (int i = 0; i < submeshCount; i++) {
SubmeshInstruction submeshInstructionItem = currentInstructions.submeshInstructions.Items[i]; SubmeshInstruction submeshInstructionItem = currentInstructions.submeshInstructions.Items[i];
meshGenerator.Begin(); meshGenerator.Begin();
@ -932,13 +941,51 @@ namespace Spine.Unity {
#endif #endif
} }
canvasRenderer.materialCount = 1; canvasRenderer.materialCount = 1;
if (assignAtCanvasRenderer) }
#if SPINE_OPTIONAL_ON_DEMAND_LOADING
if (Application.isPlaying)
HandleOnDemandLoading();
#endif
bool assignAtCanvasRenderer = (assignMeshOverrideSingle == null || !disableMeshAssignmentOnOverride);
if (assignAtCanvasRenderer) {
for (int i = 0; i < submeshCount; i++) {
CanvasRenderer canvasRenderer = canvasRenderers[i];
canvasRenderer.SetMaterial(usedMaterialItems[i], usedTextureItems[i]); canvasRenderer.SetMaterial(usedMaterialItems[i], usedTextureItems[i]);
} }
}
if (assignMeshOverrideMultiple != null) if (assignMeshOverrideMultiple != null)
assignMeshOverrideMultiple(submeshCount, meshesItems, usedMaterialItems, usedTextureItems); assignMeshOverrideMultiple(submeshCount, meshesItems, usedMaterialItems, usedTextureItems);
} }
#if SPINE_OPTIONAL_ON_DEMAND_LOADING
void HandleOnDemandLoading () {
foreach (AtlasAssetBase atlasAsset in skeletonDataAsset.atlasAssets) {
if (atlasAsset.TextureLoadingMode != AtlasAssetBase.LoadingMode.Normal) {
atlasAsset.BeginCustomTextureLoading();
if (!this.allowMultipleCanvasRenderers) {
Texture loadedTexture = null;
atlasAsset.RequireTextureLoaded(this.mainTexture, ref loadedTexture, null);
if (loadedTexture)
this.baseTexture = loadedTexture;
}
else {
Texture[] textureItems = usedTextures.Items;
for (int i = 0, count = usedTextures.Count; i < count; ++i) {
Texture loadedTexture = null;
atlasAsset.RequireTextureLoaded(textureItems[i], ref loadedTexture, null);
if (loadedTexture)
usedTextures.Items[i] = loadedTexture;
}
}
atlasAsset.EndCustomTextureLoading();
}
}
}
#endif
protected void EnsureCanvasRendererCount (int targetCount) { protected void EnsureCanvasRendererCount (int targetCount) {
#if UNITY_EDITOR #if UNITY_EDITOR
RemoveNullCanvasRenderers(); RemoveNullCanvasRenderers();

View File

@ -2,7 +2,7 @@
"name": "com.esotericsoftware.spine.spine-unity", "name": "com.esotericsoftware.spine.spine-unity",
"displayName": "spine-unity Runtime", "displayName": "spine-unity Runtime",
"description": "This plugin provides the spine-unity runtime core.", "description": "This plugin provides the spine-unity runtime core.",
"version": "4.1.28", "version": "4.1.29",
"unity": "2018.3", "unity": "2018.3",
"author": { "author": {
"name": "Esoteric Software", "name": "Esoteric Software",

View File

@ -47,9 +47,10 @@ namespace Spine.Unity.Editor {
[CustomEditor(typeof(AddressablesTextureLoader)), CanEditMultipleObjects] [CustomEditor(typeof(AddressablesTextureLoader)), CanEditMultipleObjects]
public class AddressablesTextureLoaderInspector : GenericTextureLoaderInspector { public class AddressablesTextureLoaderInspector : GenericTextureLoaderInspector {
public string LoaderSuffix { get { return "_Addressable"; } }
public class AddressablesMethodImplementations : StaticMethodImplementations { public class AddressablesMethodImplementations : StaticMethodImplementations {
public override string LoaderSuffix { get { return "_Addressable"; } }
public override GenericTextureLoader GetOrCreateLoader (string loaderPath) { public override GenericTextureLoader GetOrCreateLoader (string loaderPath) {
AddressablesTextureLoader loader = AssetDatabase.LoadAssetAtPath<AddressablesTextureLoader>(loaderPath); AddressablesTextureLoader loader = AssetDatabase.LoadAssetAtPath<AddressablesTextureLoader>(loaderPath);
if (loader == null) { if (loader == null) {

View File

@ -76,13 +76,17 @@ namespace Spine.Unity {
[System.Serializable] [System.Serializable]
public class AddressablesTextureLoader : GenericOnDemandTextureLoader<AddressableTextureReference, AddressableRequest> { public class AddressablesTextureLoader : GenericOnDemandTextureLoader<AddressableTextureReference, AddressableRequest> {
public override void CreateTextureRequest (AddressableTextureReference targetReference, public override void CreateTextureRequest (AddressableTextureReference targetReference,
MaterialOnDemandData materialData, int textureIndex, Material materialToUpdate) { MaterialOnDemandData materialData, int textureIndex, Material materialToUpdate,
System.Action<Texture> onTextureLoaded) {
OnTextureRequested(materialToUpdate, textureIndex);
materialData.textureRequests[textureIndex].handle = targetReference.assetReference.LoadAssetAsync<Texture>(); materialData.textureRequests[textureIndex].handle = targetReference.assetReference.LoadAssetAsync<Texture>();
materialData.textureRequests[textureIndex].handle.Completed += (obj) => { materialData.textureRequests[textureIndex].handle.Completed += (obj) => {
if (obj.Status == AsyncOperationStatus.Succeeded) { if (obj.Status == AsyncOperationStatus.Succeeded) {
materialToUpdate.mainTexture = (Texture)targetReference.assetReference.Asset; Texture loadedTexture = (Texture)targetReference.assetReference.Asset;
materialToUpdate.mainTexture = loadedTexture;
OnTextureLoaded(materialToUpdate, textureIndex); OnTextureLoaded(materialToUpdate, textureIndex);
if (onTextureLoaded != null) onTextureLoaded(loadedTexture);
} }
}; };
} }

View File

@ -2,7 +2,7 @@
"name": "com.esotericsoftware.spine.addressables", "name": "com.esotericsoftware.spine.addressables",
"displayName": "Spine Addressables Extensions [Experimental]", "displayName": "Spine Addressables Extensions [Experimental]",
"description": "This experimental plugin provides integration of Addressables on-demand texture loading for the spine-unity runtime.\nPlease be sure to test this package first and create backups of your project before using.\n\nUsage: First declare your target Material textures as addressable. Then select the SpineAtlasAsset, right-click the SpineAtlasAsset Inspector heading and select 'Add Addressables Loader'. This generates an 'AddressableTextureLoader' asset providing configuration parameters and sets up low-resolution placeholder textures which are automatically assigned in a pre-build step when building your game executable.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime (via the spine-unity unitypackage), version 4.1.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)", "description": "This experimental plugin provides integration of Addressables on-demand texture loading for the spine-unity runtime.\nPlease be sure to test this package first and create backups of your project before using.\n\nUsage: First declare your target Material textures as addressable. Then select the SpineAtlasAsset, right-click the SpineAtlasAsset Inspector heading and select 'Add Addressables Loader'. This generates an 'AddressableTextureLoader' asset providing configuration parameters and sets up low-resolution placeholder textures which are automatically assigned in a pre-build step when building your game executable.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime (via the spine-unity unitypackage), version 4.1.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)",
"version": "4.1.0-preview.1", "version": "4.1.0-preview.2",
"unity": "2018.3", "unity": "2018.3",
"author": { "author": {
"name": "Esoteric Software", "name": "Esoteric Software",

View File

@ -37,6 +37,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
@ -92,7 +93,7 @@ namespace Spine.Unity.Editor {
/// When set to e.g. "_Addressable", the loader asset created for /// When set to e.g. "_Addressable", the loader asset created for
/// the "Skeleton_Atlas" asset is named "Skeleton_Addressable". /// the "Skeleton_Atlas" asset is named "Skeleton_Addressable".
/// </summary> /// </summary>
public string LoaderSuffix { get; } public virtual string LoaderSuffix { get { return "_Loader"; } }
public abstract bool SetupOnDemandLoadingReference ( public abstract bool SetupOnDemandLoadingReference (
ref TargetReference targetTextureReference, Texture targetTexture); ref TargetReference targetTextureReference, Texture targetTexture);
@ -237,7 +238,7 @@ namespace Spine.Unity.Editor {
#if NEWPLAYMODECALLBACKS #if NEWPLAYMODECALLBACKS
static void OnPlaymodeChanged (PlayModeStateChange mode) { static void OnPlaymodeChanged (PlayModeStateChange mode) {
bool assignTargetTextures = mode == PlayModeStateChange.ExitingPlayMode; bool assignTargetTextures = mode == PlayModeStateChange.EnteredEditMode;
#else #else
static void OnPlaymodeChanged () { static void OnPlaymodeChanged () {
bool assignTargetTextures = !Application.isPlaying; bool assignTargetTextures = !Application.isPlaying;
@ -259,15 +260,24 @@ namespace Spine.Unity.Editor {
public static void AssignTargetTexturesAtLoader (OnDemandTextureLoader loader) { public static void AssignTargetTexturesAtLoader (OnDemandTextureLoader loader) {
List<Material> placeholderMaterials; List<Material> placeholderMaterials;
List<Material> nullTextureMaterials;
bool anyPlaceholdersAssigned = loader.HasPlaceholderTexturesAssigned(out placeholderMaterials); bool anyPlaceholdersAssigned = loader.HasPlaceholderTexturesAssigned(out placeholderMaterials);
if (anyPlaceholdersAssigned) { bool anyMaterialNull = loader.HasNullMainTexturesAssigned(out nullTextureMaterials);
Debug.Log("OnDemandTextureLoader detected placeholders assigned at one or more materials. Resetting to target textures.", loader); if (anyPlaceholdersAssigned || anyMaterialNull) {
Debug.Log("OnDemandTextureLoader detected placeholders assigned or null main textures at one or more materials. Resetting to target textures.", loader);
AssetDatabase.StartAssetEditing(); AssetDatabase.StartAssetEditing();
IEnumerable<Material> modifiedMaterials; IEnumerable<Material> modifiedMaterials;
loader.AssignTargetTextures(out modifiedMaterials); loader.AssignTargetTextures(out modifiedMaterials);
if (placeholderMaterials != null) {
foreach (Material placeholderMaterial in placeholderMaterials) { foreach (Material placeholderMaterial in placeholderMaterials) {
EditorUtility.SetDirty(placeholderMaterial); EditorUtility.SetDirty(placeholderMaterial);
} }
}
if (nullTextureMaterials != null) {
foreach (Material nullTextureMaterial in nullTextureMaterials) {
EditorUtility.SetDirty(nullTextureMaterial);
}
}
AssetDatabase.StopAssetEditing(); AssetDatabase.StopAssetEditing();
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
} }

View File

@ -164,6 +164,7 @@ namespace Spine.Unity {
if (placeholderMaterials == null) placeholderMaterials = new List<Material>(); if (placeholderMaterials == null) placeholderMaterials = new List<Material>();
placeholderMaterials.Add(material); placeholderMaterials.Add(material);
} }
materialIndex++;
} }
return anyPlaceholderAssigned; return anyPlaceholderAssigned;
} }
@ -180,8 +181,7 @@ namespace Spine.Unity {
atlasAsset, i + 1, targetMaterial), this); atlasAsset, i + 1, targetMaterial), this);
return false; return false;
} }
Material ignoredArgument = null; AssignTargetTextures(targetMaterial, i);
RequestLoadMaterialTextures(targetMaterial, ref ignoredArgument);
++i; ++i;
} }
modifiedMaterials = atlasAsset.Materials; modifiedMaterials = atlasAsset.Materials;
@ -223,7 +223,7 @@ namespace Spine.Unity {
int foundMaterialIndex = Array.FindIndex(placeholderMap, entry => entry.textures[textureIndex].placeholderTexture == currentTexture); int foundMaterialIndex = Array.FindIndex(placeholderMap, entry => entry.textures[textureIndex].placeholderTexture == currentTexture);
if (foundMaterialIndex >= 0) if (foundMaterialIndex >= 0)
RequestLoadTexture(material, foundMaterialIndex, textureIndex); RequestLoadTexture(material, foundMaterialIndex, textureIndex, null);
int loadedMaterialIndex = Array.FindIndex(loadedDataAtMaterial, entry => int loadedMaterialIndex = Array.FindIndex(loadedDataAtMaterial, entry =>
entry.textureRequests[textureIndex].WasRequested && entry.textureRequests[textureIndex].WasRequested &&
@ -232,33 +232,69 @@ namespace Spine.Unity {
loadedDataAtMaterial[loadedMaterialIndex].lastFrameRequested = Time.frameCount; loadedDataAtMaterial[loadedMaterialIndex].lastFrameRequested = Time.frameCount;
} }
protected virtual void RequestLoadTexture (Material material, int materialIndex, int textureIndex) { public override void RequestLoadTexture (Texture placeholderTexture, ref Texture replacementTexture,
System.Action<Texture> onTextureLoaded = null) {
if (placeholderTexture == null) return;
Texture currentTexture = placeholderTexture;
int textureIndex = 0; // Todo: currently only main texture is supported.
int foundMaterialIndex = Array.FindIndex(placeholderMap, entry => entry.textures[textureIndex].placeholderTexture == currentTexture);
if (foundMaterialIndex >= 0) {
Material material = atlasAsset.Materials.ElementAt(foundMaterialIndex);
Texture loadedTexture = RequestLoadTexture(material, foundMaterialIndex, textureIndex, onTextureLoaded);
if (loadedTexture != null)
replacementTexture = loadedTexture;
}
int loadedMaterialIndex = Array.FindIndex(loadedDataAtMaterial, entry =>
entry.textureRequests[textureIndex].WasRequested &&
entry.textureRequests[textureIndex].IsTarget(placeholderTexture));
if (loadedMaterialIndex >= 0)
loadedDataAtMaterial[loadedMaterialIndex].lastFrameRequested = Time.frameCount;
}
protected void AssignTargetTextures (Material material, int materialIndex) {
int textureIndex = 0; // Todo: currently only main texture is supported.
RequestLoadTexture(material, materialIndex, textureIndex, null);
}
protected virtual Texture RequestLoadTexture (Material material, int materialIndex, int textureIndex,
System.Action<Texture> onTextureLoaded) {
PlaceholderTextureMapping[] placeholderTextures = placeholderMap[materialIndex].textures; PlaceholderTextureMapping[] placeholderTextures = placeholderMap[materialIndex].textures;
TargetReference targetReference = placeholderTextures[textureIndex].targetTextureReference; TargetReference targetReference = placeholderTextures[textureIndex].targetTextureReference;
loadedDataAtMaterial[materialIndex].lastFrameRequested = Time.frameCount; loadedDataAtMaterial[materialIndex].lastFrameRequested = Time.frameCount;
#if UNITY_EDITOR #if UNITY_EDITOR
if (!Application.isPlaying) { if (!Application.isPlaying) {
if (targetReference.EditorTexture != null) if (targetReference.EditorTexture != null) {
material.mainTexture = targetReference.EditorTexture; material.mainTexture = targetReference.EditorTexture;
return; if (onTextureLoaded != null) onTextureLoaded(targetReference.EditorTexture);
}
return targetReference.EditorTexture;
} }
#endif #endif
MaterialOnDemandData materialData = loadedDataAtMaterial[materialIndex]; MaterialOnDemandData materialData = loadedDataAtMaterial[materialIndex];
if (materialData.textureRequests[textureIndex].WasRequested) { if (materialData.textureRequests[textureIndex].WasRequested) {
Texture loadedTexture = GetAlreadyLoadedTexture(materialIndex, textureIndex); Texture loadedTexture = GetAlreadyLoadedTexture(materialIndex, textureIndex);
if (loadedTexture != null) if (loadedTexture != null) {
material.mainTexture = loadedTexture; material.mainTexture = loadedTexture;
return; if (onTextureLoaded != null) onTextureLoaded(loadedTexture);
}
return loadedTexture;
} }
CreateTextureRequest(targetReference, materialData, textureIndex, material); CreateTextureRequest(targetReference, materialData, textureIndex, material, onTextureLoaded);
return null;
} }
public abstract Texture GetAlreadyLoadedTexture (int materialIndex, int textureIndex); public abstract Texture GetAlreadyLoadedTexture (int materialIndex, int textureIndex);
public abstract void CreateTextureRequest (TargetReference targetReference, public abstract void CreateTextureRequest (TargetReference targetReference,
MaterialOnDemandData materialData, int textureIndex, Material materialToUpdate); MaterialOnDemandData materialData, int textureIndex, Material materialToUpdate,
System.Action<Texture> onTextureLoaded);
public virtual void UnloadUnusedTextures () { public virtual void UnloadUnusedTextures () {
int currentFrameCount = Time.frameCount; int currentFrameCount = Time.frameCount;

View File

@ -2,7 +2,7 @@
"name": "com.esotericsoftware.spine.on-demand-loading", "name": "com.esotericsoftware.spine.on-demand-loading",
"displayName": "Spine On-Demand Loading Extensions [Experimental]", "displayName": "Spine On-Demand Loading Extensions [Experimental]",
"description": "This experimental plugin provides a generic basic implementation of on-demand texture loading for the spine-unity runtime. You might want to use the available com.esotericsoftware.spine.addressables package which depends on this package.\nPlease be sure to test this package first and create backups of your project before using.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime (via the spine-unity unitypackage), version 4.1.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)", "description": "This experimental plugin provides a generic basic implementation of on-demand texture loading for the spine-unity runtime. You might want to use the available com.esotericsoftware.spine.addressables package which depends on this package.\nPlease be sure to test this package first and create backups of your project before using.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime (via the spine-unity unitypackage), version 4.1.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)",
"version": "4.1.0", "version": "4.1.0-preview.2",
"unity": "2018.3", "unity": "2018.3",
"author": { "author": {
"name": "Esoteric Software", "name": "Esoteric Software",