我尝试将Mix and Match Equip示例 和 Per Instance Material Properties示例的内容组合使用,但结果是Per Instance Material Properties中任何更改的材质属性都没有效果,我检查了shader,是否是因为混合皮肤导致shader一直是spine/skeleton。如何才能做到在使用混合皮肤的情况下,更改角色的渲染器?
我的代码示例如下:

    baseSkin = "skin/" + name;
        Skeleton skeleton = skeletonAnimation.Skeleton;
        SkeletonData skeletonData = skeleton.Data;

        characterSkin = new Skin("character-base");
        characterSkin.AddSkin(skeletonData.FindSkin(baseSkin));
        if (isNotGetW)
		{
			return;
		}
		
        characterSkin.AddSkin(skeletonData.FindSkin(weaPonSkins));
		Skeleton skeleton = skeletonAnimation.Skeleton;
		Skin resultCombinedSkin = new Skin("character-combined");

		resultCombinedSkin.AddSkin(characterSkin);
		

		Skeleton skeleton = skeletonAnimation.Skeleton;
		SkeletonData skeletonData = skeleton.Data;

		skeleton.SetSkin(resultCombinedSkin);
		skeleton.SetSlotsToSetupPose();
        MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        mpb.SetFloat("_GrayPhase", 0.7f);
        enemyAnimator.GetComponent<SkeletonAnimation>().GetComponent<Renderer>().SetPropertyBlock(mpb);
Related Discussions
...

在使用混合皮肤的同时更改角色的渲染器属性时,您需要确保正确使用 MaterialPropertyBlock。在您的代码中,您已经创建了一个 MaterialPropertyBlock 并设置了 _GrayPhase 属性,但需要确保在正确的渲染器上应用此属性块。

以下是一些可能的改进建议:

  1. 确保 enemyAnimator.GetComponent<SkeletonAnimation>().GetComponent<Renderer>() 返回的是您期望的渲染器。如果 SkeletonAnimation 组件不在 enemyAnimator 上,您可能需要调整获取组件的方式。

  2. 确保在设置 MaterialPropertyBlock 后,渲染器的材质属性确实被更新。您可以在调试时检查 Renderer 上的材质属性是否发生了变化。

  3. 如果您使用的是 SkeletonGraphic 而不是 SkeletonAnimation,请注意它们的处理方式可能会有所不同。

  4. 确保您的自定义着色器支持您想要更改的属性。如果着色器不支持 _GrayPhase,则更改不会生效。

以下是一个示例代码片段,展示如何正确应用 MaterialPropertyBlock

MaterialPropertyBlock mpb = new MaterialPropertyBlock();
mpb.SetFloat("_GrayPhase", 0.7f);
Renderer renderer = enemyAnimator.GetComponent<SkeletonAnimation>().GetComponent<Renderer>();
if (renderer != null) {
    renderer.SetPropertyBlock(mpb);
}

确保在应用 MaterialPropertyBlock 之前,您已经正确设置了皮肤和插槽。

@fengmin I'm not sure I understand your problem description, as machine translation was not very clear.

Please note that the Material and Shader properties are not modified when changing skins or setting skins active. They have the settings you define in your _Material asset in your Project window next to the skeleton assets. It's just that different skins might require different atlas pages, and thus change the active Material to the respective atlas page Materials. Did you change these Material assets?

MaterialPropertyBlock mpb = new MaterialPropertyBlock();
mpb.SetFloat("_GrayPhase", 0.7f);

This code does not change the active shader at the material, it just sets a Material property (which does not exist at the default shader) to value 0.7.

For more info, see the documentation here:
https://zh.esotericsoftware.com/spine-unity-rendering#Materials

    Harald
    谢谢,我的做法是:先通过skeletonData创建skeletonanimation动画对象(Spine GameObject),然后手动修改其shader为Spine/special/skeleton Grayscale,最后代码中调整MaterialPropertyBlock mpb = new MaterialPropertyBlock();
    mpb.SetFloat("_GrayPhase", 0.7f);
    到这一步都没问题,但是当我尝试融入Mix and Match Equip示例中的代码时,混合后Spine GameObject的shader被改回了spine/skeleton且每帧都在修改,导致我无法再对其进行操作

    @fengmin Then likely you are setting your material with the different shader the wrong way. Your code above does not show how you do that, but I guess that you modified a material instance and then the Material gets replaced with the main asset materials automatically, overriding your material modifications again. This is explained in the documentation section that I linked in my previous posting, SkeletonRenderer manages materials for you:
    https://zh.esotericsoftware.com/spine-unity-rendering#Materials

      Harald 谢谢,现在我知道错误的原因了,请问正确的做法是什么?我希望将Mix and Match Equip示例 和 Per Instance Material Properties示例结合使用,先混合角色皮肤后为不同角色添加不同程度的特殊材质效果

      @fengmin The problem should not be using Mix and Match or using skins. You should be either modifying the skeleton's _Material assets (next to your other exported skeleton assets) if you want to set a special shader for all skeleton Instances and never want to use the default Spine/Skeleton shader.

      Otherwise if you want to assign a custom Material, you have the options in the documentation:
      https://zh.esotericsoftware.com/spine-unity-rendering#Materials
      You could be using the SkeletonRendererCustomMaterials component or using SkeletonRenderer.CustomMaterialOverride programmatically.

      MaterialPropertyBlock unfortunately can't change the shader, so you have to use a different material. You can use MaterialPropertyBlock each frame to change a float Material property though.

      Apart from that, if you are repacking a Skin via GetRepackedSkin() you can also set the Material materialPropertySource parameter (see here) to the desired template Material, of which the shader settings will be used, or use the GetRepackedSkin() variant providing a Shader shader property (see here).