Sorry for that, I will try to word my reply better and add more details.
This is the first project I've worked on that has Spine in it, we were tasked with migrating an old cocos2d-x project into Unity. The old cocos2d-x project used Spine 3.8, we have 4.2 (latest?) on Unity. All the assets were migrated to 4.2 using the migration scripts on github.
As mentioned in the first post, because of the sheer amount of assets, we do not want to import everything into Unity.
During the asset check, we found that some animations were not properly displaying after loading them using the following code:
SpineAtlasAsset runtimeAtlas = SpineAtlasAsset.CreateRuntimeInstance(new TextAsset(File.ReadAllText(Path.Combine(directoryPath, fileName + ".atlas.txt"))), textures, skeletonGraphicDefaultMaterial, true);
SpineDataAsset runtimeSkeletonDataAsset = SkeletonDataAsset.CreateRuntimeInstance(new TextAsset(File.ReadAllText(Path.Combine(directoryPath, fileName + ".json"))), runtimeAtlas, true);
SpineGraphic uiObject = SkeletonGraphic.NewSkeletonGraphicGameObject(runtimeSkeletonDataAsset, worldTransform, skeletonGraphicDefaultMaterial);
The files are stored in a separate directory and contain only the following files:
- Skeleton JSON - filename.json
- Texture File(s) - filename[#].png
- Atlas file - filename.atlas.txt
For most of the assets, the above code is enough to instantiate the spine objects for our artists to do the asset check. However it was found during the asset check that animations which included blend modes were not being properly loaded.
In standard developer fashion, I imported one of the assets into Unity to try and get it to work. I modified the script to load the assets as follows:
SpineDataAsset runtimeSkeletonDataAsset = Resources.Load<SkeletonDataAsset>(lookupPath);
SpineGraphic uiObject = SkeletonGraphic.NewSkeletonGraphicGameObject(runtimeSkeletonDataAsset, worldTransform, skeletonGraphicDefaultMaterial);
In addition to this, we enable Multiple Canvas Renderers for all objects by default and we start the pre-set animation loop so that we can verify each of them
uiObject.allowMultipleCanvasRenderers = true;
uiObject.AnimationState.SetAnimation(0, animationName, true);
During testing we instantiated the same object using both methods, once for the external files, once for the same asset after being imported into Unity.
Upon further inspection, I decided to check the SkeletonDataAsset generated by unity on the imported asset. I noticed that the Skeleton had blend mode materials assigned to it but they were not being applied.
That's when I posted the original question above.
After checking the response from the bot, I gave it a go. It... didn't work. At this point I'm still not sure if I'm doing the right thing.
var blendModeMaterials = uiObject.skeletonDataAsset.blendModeMaterials;
Debug.Log($"Blend Materials: Add[{blendModeMaterials.additiveMaterials.Count}] Mult[{blendModeMaterials.multiplyMaterials.Count}] Screen[{blendModeMaterials.screenMaterials.Count}]");
blendModeMaterials.screenMaterials[0].material = skeletonGraphicDefaultMaterial_Screen;
blendModeMaterials.multiplyMaterials[0].material = skeletonGraphicDefaultMaterial_Multiply;
blendModeMaterials.ApplyMaterials(uiObject.SkeletonData);
When running the above code on the assets imported by Unity, it throws an exception when replacing the multiply materials.
Blend Materials: Add[5] Mult[0] Screen[4]
UnityEngine.Debug:Log (object)
SpineLoadingTest:LoadUIObject () (at Assets/Scripts/Sandbox/Spine/SpineLoadingTest.cs:238)
SpineLoadingTest:LoadUIObjectOnClick () (at Assets/Scripts/Sandbox/Spine/SpineLoadingTest.cs:224)
UnityEngine.EventSystems.EventSystem:Update () (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:530)
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <4b234520e36749be9cf6b053d911690f>:0)
SpineLoadingTest.LoadUIObject () (at Assets/Scripts/Sandbox/Spine/SpineLoadingTest.cs:240)
SpineLoadingTest.LoadUIObjectOnClick () (at Assets/Scripts/Sandbox/Spine/SpineLoadingTest.cs:224)
UnityEngine.Events.InvokableCall.Invoke () (at <228a75ed9d5b4a658c89f48527e7e2e0>:0)
UnityEngine.Events.UnityEvent.Invoke () (at <228a75ed9d5b4a658c89f48527e7e2e0>:0)
UnityEngine.UI.Button.Press () (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114)
UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57)
UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272)
UnityEngine.EventSystems.EventSystem:Update() (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:530)
Running the same code against the assets in the external folder we also get an exception but this time is one line earlier, which points to the line where the screen materials are set.
Blend Materials: Add[0] Mult[0] Screen[0]
UnityEngine.Debug:Log (object)
SpineLoadingTest:LoadUIObject () (at Assets/Scripts/Sandbox/Spine/SpineLoadingTest.cs:238)
SpineLoadingTest:LoadUIObjectOnClick () (at Assets/Scripts/Sandbox/Spine/SpineLoadingTest.cs:224)
UnityEngine.EventSystems.EventSystem:Update () (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:530)
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <4b234520e36749be9cf6b053d911690f>:0)
SpineLoadingTest.LoadUIObject () (at Assets/Scripts/Sandbox/Spine/SpineLoadingTest.cs:239)
SpineLoadingTest.LoadUIObjectOnClick () (at Assets/Scripts/Sandbox/Spine/SpineLoadingTest.cs:224)
UnityEngine.Events.InvokableCall.Invoke () (at <228a75ed9d5b4a658c89f48527e7e2e0>:0)
UnityEngine.Events.UnityEvent.Invoke () (at <228a75ed9d5b4a658c89f48527e7e2e0>:0)
UnityEngine.UI.Button.Press () (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114)
UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57)
UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272)
UnityEngine.EventSystems.EventSystem:Update() (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:530)
In this case, the logs also show that the blend materials are not set at all for the latter.
I then commented out the lines which set the materials and left only the ApplyMaterials line to see if it would have any effect, still nothing. I played around with the BlendModeMaterials class and found the RequiresBlendModeMaterials
flag which if set to true, makes an extra option appear in the Advanced tab, in the inspector. I also noticed, however, that the Multiply Material and Screen Material have not been assigned (they're showing as None). So in runtime , I assigned the materials in the inspector with the ones provided here:
- Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Materials/SkeletonGraphic-StaightAlphaTexture
- SkeletonGraphicMultiply-Straight
- SkeletonGraphicScreen-Straight
And that made the animation display correctly. However I don't know how to achieve the same result from code, when using the assets loaded from the external folder.
Any help would be greatly appreciated.