WiseKodama

Greetings,

I am wondering whether it is expected behaviour, that material instance that has been set as an override, does not visually update on the skeleton despite the material instance being updated.
I would assume that if I modify the tintMaterialInstance that the modifications should be visible on the SkeletonRenderer, however they are not
private void FixedUpdate(){
if( tintMaterialInstance == null )
{
tintShader = Shader.Find( "Spine/Skeleton Tint" );
originalMaterial = spineCreature.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
tintMaterialInstance = Instantiate( originalMaterial );
tintMaterialInstance.shader = tintShader;
spineCreature.CustomMaterialOverride[originalMaterial] = tintMaterialInstance;
}

tintMaterialInstance.SetColor( "_Black", Color.Lerp( Color.black, Color.white, percent ) );
}
WiseKodama
  • Mesajlar: 11

Harald

Unfortunately we could not reproduce this behaviour, the following test script (based on MaterialReplacementExample from the Per Instance Material Properties example scene) works as expected:
using UnityEngine;

namespace Spine.Unity.Examples {
public class MaterialReplacementExample2 : MonoBehaviour {

public Material originalMaterial;
public Material replacementMaterialTemplate;
protected Material replacementMaterialInstance;
public SkeletonAnimation skeletonAnimation;

[Space]
public string phasePropertyName = "_GrayPhase";
[Range(0f, 1f)] public float phase = 1f;

void Start () {
if (originalMaterial == null)
originalMaterial = skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;

replacementMaterialInstance = Instantiate(replacementMaterialTemplate);
skeletonAnimation.CustomMaterialOverride[originalMaterial] = replacementMaterialInstance;
}

void Update () {
replacementMaterialInstance.SetFloat(phasePropertyName, phase);
}
}
}
Are you sure that there is no other script interfering with your code?

Which version of the spine-unity runtime (name of the unitypackage, also listed in Assets/Spine/version.txt) are you using?
Kullanıcı avatarı
Harald

Harri
  • Mesajlar: 4449

WiseKodama

Thanks for the reply.

We are using v3.8, unfortunately I am not seeing the example scene in the project.

To verify that the values are correct I checked this:
Debug.Log( $"qqq{tintMaterialInstance.GetHashCode()} {tintMaterialInstance.GetColor("_Black")}" +
$" {spineCreature.CustomMaterialOverride[originalMaterial].GetHashCode()} {spineCreature.CustomMaterialOverride[originalMaterial].GetColor("_Black")}" );
Output:


I've checked the materials in editor as well.

MeshRenderer material:


TintMaterialInstance:


The material that I see on the mesh renderer therefore does not match with the override.
I would expect that setting an override would then assign the override material in editor and use that to render.
WiseKodama
  • Mesajlar: 11

Harald

WiseKodama yazdı:We are using v3.8, unfortunately I am not seeing the example scene in the project.
This example scene exists since at least spine-unity 3.6, if you don't see it then you have perhaps not imported the whole unitypackage, or deleted the asset.

Which exact version of the spine-unity runtime are you using? spine-unity 3.8 has seen 165 package releases from 2019 to 2021. You can see it in the name of the unitypackage, also listed in Assets/Spine/version.txt.
I would expect that setting an override would then assign the override material in editor and use that to render.
Do you mean outside of play-mode, or after entering play-mode?
Kullanıcı avatarı
Harald

Harri
  • Mesajlar: 4449

WiseKodama

Package version: spine-unity-3.8-2020-08-12.unitypackage
After entering play-mode. We are not doing anything outside playmode.
WiseKodama
  • Mesajlar: 11

Harald

WiseKodama yazdı:Package version: spine-unity-3.8-2020-08-12.unitypackage
You could have a quick test if perhaps the latest spine-unity 3.8 runtime (spine-unity 3.8 2021-11-10) already fixes your issue. As usual, please be sure to backup your project before upgrading.

You can download if from here as usual:
spine-unity Download: Older Versions
Kullanıcı avatarı
Harald

Harri
  • Mesajlar: 4449

WiseKodama

Apologies Harald, I was unable to perform the change sooner.

The result is the same with the spine-unity 3.8 runtime(2021-11-10).

To clarify, I can make this work with MaterialPropertyBlocks, but to me it seems that it should work just by updating the material instance.

---

Just debugged this a bit more and found the issue. Basically if you have mask behaviours, they have different materials, and if you override an original material, it overrides ONLY for that mask "type"(none, outside or inside), should the required masking material change then it will no longer work.

If I set the Mask Interaction to none, then my initial code above works fine, modifying the material instance renders immediate results, however if a new material takes over for masking everything breaks.

Is there at least any way of detecting this change? So that I would know when the skeleton receives the different masking material so that I could set override anew?

Or an even more important question is... Should I just make all our spine materials use Spine/Skeleton-Tint shader and just use MaterialPropertyBlocks?
WiseKodama
  • Mesajlar: 11

Harald

No need to apologize, thanks very much for the additional info and for digging into this issue!

We have created an issue ticket here:
https://github.com/EsotericSoftware/spine-runtimes/issues/2191
Please note that the bugfix will either be implemented on the 4.1 or 4.2-beta branch (depending on the changes have the potential to break existing projects), and you would likely need to port any bugfix commits to 3.8 yourself.
WiseKodama yazdı:Should I just make all our spine materials use Spine/Skeleton-Tint shader and just use MaterialPropertyBlocks?
This could be a good workaround for now until this issue has been resolved.

An alternative solution would be to not use Mask Interaction Mode to switch to mask-materials but instead setup the main material to have the Stencil properties setup for maskin (you could copy the properties from the mask materal to the main material).

---

After some more evaluation we have come to the conclusion that unfortunately no solution can be implemented which fits all use cases (and is not additionally cluttering the SkeletonRenderer interface). The problem is that when using CustomMaterialOverride to override the primary material with e.g. a tinted one and having the mask mode set to Inside Mask, most users will expect the mask mode to still be respected automatically in their override material. We decided against adding an additional CustomMaterialOverrideMasked property which would replace materials after mask materials have been assigned, since this adds too much code overhead (and complexity, potentially leading to confusion) just for a single use case.

As a result, we would recommend to
  • a) use MaterialPropertyBlock as you've described above, or
  • b) set material properties after the materials have been replaced and assigned at the MeshRenderer by registering to the SkeletonRenderer.OnMeshAndMaterialsUpdated callback. You could immediately unregister from the callback again once the required material property changes have been applied.
Kullanıcı avatarı
Harald

Harri
  • Mesajlar: 4449


Dön Unity