I want to assign UnityEngine.U2D.Animation.SpriteSkin to my gameObject programmatically.
My object has SpiteRenderer. I assign Sprite with configured bones to it.
After that, I create the Sprite bones structure using the code I copied from UnityEngine.U2D.Animation.SpriteSkinUtility.CreateBoneHierarchy
var spriteBones = spriteRenderer.sprite.GetBones();
var boneTransforms = new Transform[spriteBones.Length];
Transform rootBone = null;
for (var i = 0; i < spriteBones.Length; ++i)
{
CreateBoneGameObject(i, spriteBones, boneTransforms, transform);
if (spriteBones[i].parentId < 0 && rootBone == null)
{
rootBone = boneTransforms[i];
}
}
static void CreateBoneGameObject(int index, SpriteBone[] spriteBones, Transform[] transforms, Transform root)
{
if (transforms[index] != null) return;
var spriteBone = spriteBones[index];
if (spriteBone.parentId >= 0)
{
CreateBoneGameObject(spriteBone.parentId, spriteBones, transforms, root);
}
var go = new GameObject(spriteBone.name);
var transform = go.transform;
if (spriteBone.parentId >= 0)
{
transform.SetParent(transforms[spriteBone.parentId]);
}
else
{
transform.SetParent(root);
}
transform.localPosition = spriteBone.position;
transform.localRotation = spriteBone.rotation;
transform.localScale = Vector3.one;
transforms[index] = transform;
}
After that I add SpriteSkin to my object
var spriteSkin = GetComponent<SpriteSkin>();
if (spriteSkin == null)
{
spriteSkin = gameObject.AddComponent<SpriteSkin>();
spriteSkin.enabled = true;
}
But SpriteSkin properties rootBone and boneTransforms are internal and cannot be changed.
I was still able to change them using reflection like this:
var rootBoneProperty = typeof(SpriteSkin).GetProperty(nameof(SpriteSkin.rootBone));
rootBoneProperty!.SetValue(spriteSkin, rootBone, BindingFlags.NonPublic | BindingFlags.Instance, null, null, CultureInfo.InvariantCulture);
//spriteSkin.rootBone = rootBone;
var boneTransformsProperty = typeof(SpriteSkin).GetProperty(nameof(SpriteSkin.boneTransforms));
boneTransformsProperty!.SetValue(spriteSkin, boneTransforms, BindingFlags.NonPublic | BindingFlags.Instance, null, null, CultureInfo.InvariantCulture);
//spriteSkin.boneTransforms = boneTransforms;
After that, I add the Animator component to the object, and the animation works as expected.
But that’s probably not the best solution.
Am I missing some obvious way of setting SpriteSkin data at runtime,
Or programmatically changing bones is not supported intentionally?