- Изменено
[Unity] Constant distance between object and bone
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);
}
}