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.