• Runtimes
  • [Unity] Constant distance between object and bone

  • Изменено
Related Discussions
...

I am using Bone Component for attaching my object to bones, but sometimes I want my object to be in the same distance to bone.
In my game I had to attach spear to head (spine bone). I do not wanted to attach it to the center of a bone, but to a certain position in head. Keep constant distance and constant angle between bone and spear during animation.
See gif below:

I could not find such a component, that is why I wrote it myself. Feel free to use it. Just add script to object, choose SkeletonAnimation and write bone name.

using System.Collections;
using UnityEngine;
using Spine;

public class BoneDistanceComponent : MonoBehaviour {

   public SkeletonRenderer skeletonRenderer;
   public string boneName;

   private float startObjectRotation;
   private float startBoneRotation;
   private float distanceBoneObject;
   private float angleBoneObject;

   void BoneObjectDistance(string boneName)
   {
      skeletonRenderer.skeleton.UpdateWorldTransform();

  startObjectRotation = transform.eulerAngles.z;
  startBoneRotation = skeletonRenderer.skeleton.FindBone(boneName).worldRotation;

  var boneX = skeletonRenderer.skeleton.FindBone(boneName).WorldX * skeletonRenderer.transform.localScale.x + skeletonRenderer.transform.position.x;
  var boneY = skeletonRenderer.skeleton.FindBone(boneName).WorldY * skeletonRenderer.transform.localScale.y + skeletonRenderer.transform.position.y;

  var diffBoneObjectX = boneX - transform.position.x;
  var diffBoneObjectY = boneY - transform.position.y;

  distanceBoneObject = Mathf.Sqrt(Mathf.Pow(diffBoneObjectX, 2f) + Mathf.Pow(diffBoneObjectY, 2f));
  angleBoneObject = Mathf.Atan2(diffBoneObjectY, diffBoneObjectX);
   }

   void Start() 
   {
      BoneObjectDistance(boneName);
   }

   void Update()
   {
      transform.position = new Vector2(
         skeletonRenderer.skeleton.FindBone(boneName).WorldX * skeletonRenderer.transform.localScale.x + skeletonRenderer.transform.position.x - 
         Mathf.Cos(angleBoneObject + (skeletonRenderer.skeleton.FindBone(boneName).worldRotation - startObjectRotation) * Mathf.Deg2Rad) * distanceBoneObject,
         skeletonRenderer.skeleton.FindBone(boneName).WorldY * skeletonRenderer.transform.localScale.y + skeletonRenderer.transform.position.y - 
         Mathf.Sin(angleBoneObject + (skeletonRenderer.skeleton.FindBone(boneName).worldRotation - startObjectRotation) * Mathf.Deg2Rad) * distanceBoneObject);
      transform.rotation = Quaternion.Euler(0,0, startObjectRotation + skeletonRenderer.skeleton.FindBone(boneName).worldRotation - startBoneRotation);
   }
}