- Изменено
Different materials for same Spine character
Hello all. The situation I am running into is as such: I have one gameobject with a skeleton Mesh, mesh renderer, skeleton animation script and material on it. However I want to be able to use this gameobject for multiple different scenes, and have each use a different main color on the material. However with the way Spine SDK works, I can't replace the element 0 on the mesh renderer with anything else. And, as expected, any modifications I make to the material are made across all instances since the material is shared. The only way to circumvent this is to create a separate Atlas/SkeletonData/etc... for each unique instance of the same model, which of course takes up more memory than just having multiple materials. Anyone know what I can do to achieve my desired result?
So you want each instance of SkeletonAnimation using a shared SkeletonDataAsset to use a different Material.
Sounds easy enough.
Let me help you look into it.
The SkeletonRenderer code is actually the thing pulling the Material references from the AtlasAsset. And as you've observed, it does this every frame. It does so because multi-atlas setups potentially change the number, order and source of Materials at any given point.
I think the easy way to do this is to add any MonoBehaviour with this method on it to the same GameObject. Like this.
public class SkeletonMaterialReplacer : MonoBehaviour {
public Material materialToReplace;
public Material meterialIWantToUse;
public MeshRenderer meshRenderer;
void OnWillRenderObject ()
{
if (meshRenderer.sharedMaterial == materialToReplace) {
meshRenderer.sharedMaterial = meterialIWantToUse;
}
/*
// Use this for multi-material setups.
var sharedMaterials = meshRenderer.sharedMaterials;
for (int i = 0; i < sharedMaterials.Length; i++) {
if (sharedMaterials[i] == materialToReplace) {
sharedMaterials[i] = meterialIWantToUse;
}
}
meshRenderer.sharedMaterials = sharedMaterials;
*/
}
}
Basically, we're putting it on OnWillRenderObject (http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnWillRenderObject.html) so that it happens after SkeletonRenderer's LateUpdate (which builds the mesh and sets the material array).
I think that'll work. Of course, I haven't put null checks or enabled/disabled checks in there. Just wanted to get the point across.
More on MonoBehaviour method execution order here: http://docs.unity3d.com/Manual/ExecutionOrder.html
A more straightforward API-like way to do this is probably a lot more work and modifications to low-level classes.
You're a door knob cleaner now?
Pharan, thanks so much for this post. I was looking for this solution for a day now and tried quite a few things!