What you're doing is a special case where your SkeletonAnimation only exists at runtime and not in Unity editor.
(I think this is a little unusual, but certainly valid use if you have a LOT of skeleton jsons and making a prefab for each one is nonsense.)
The setup procedure is a bit specific in this case. There may even be an un-accounted-for bug. So let's run through this.
Normally, an existing SkeletonAnimation that was set up in the editor will have its Awake called first.
The current design does these in this order:
Scene starts. Objects get deserialized. Unity calls
Reset runs first. It instantiates the components internal meshes and the vertex buffer for rendering.
It will force the SkeletonData JSON to parse and load if it wasn't loaded already, then instantiate a new Spine.Skeleton. (it will orphan an old Skeleton of it existed)
Then it calls
LateUpdate once which causes it to initially render the skeleton's base pose.
Reset runs. This will instantiate a new Spine.AnimationState based on the data you typed into your SkeletonDataAsset.
By the end of all this, the Spine data structures should have already been instantiated, and your mesh should already have been generated and visible.
But, if the SkeletonAnimation/SkeletonRenderer's skeletonDataAsset field was null, it will stop at Step 2.
This is important: In Unity, calling AddComponent will immediately call that component's Awake method before the AddComponent method returns.
This means using AddComponent to instantiate a SkeletonAnimation will (1) always throw an error complaining that there wasn't a skeletonDataAsset assigned. But you can fix that with some small edits to SkeletonRenderer.cs (2) need you to call Reset yourself after you've assigned proper values in its fields.
Therefore, I expect your code to work properly if you did this:
playerAnim = (SkeletonAnimation)(gameObject.AddComponent<SkeletonAnimation>());
// gives you an error. "Missing SkeletonData asset." That's okay. Carry on.
// assign the right values.
playerAnim.skeletonDataAsset = playerData;
playerAnim.calculateNormals = true;
playerAnim.loop = false;
// Now that the values are there. Call Reset.
// The mesh should have been rendered by Reset's LateUpdate call at this point. You can now disable it.
playerAnim.enabled = false;
I could be wrong. Please share your findings.
Whenever you change the colors of slots, you need to call
playerAnim.LateUpdate() so the mesh colors update.
EDIT: Dear future reader, this code does not work. Please see my next post below.