- Изменено
Unity Canvas position to Bone position
Hello,
I have a character with a few bones.
I want to be able to drag bone part.
I do not drag directly the bone part , but drag an empty sprite with 2d Box collider and kemantic rigidbody.
When i start dragging the sprite collider i have an event that pops up with the unity world position of the touch/mouse.
and i do:
private void Dragging(Vector2 pos)
{
Spine.Bone bone = SpineAnimation.Skeleton.FindBone("bone2");
bone.worldX = pos.x;
bone.worldY = pos.y;
}
The bone is now drag-able but not positioned correctly, like moving on a smaller world space scale.
Like if i drag to the top of the screen it get close to reach the collider sprite, but it is not synced , but if i drag to bottom it does fit sprite position (only at most bottom area).
Help here please.
A Spine.Bone
object's worldX
and worldY
are actually a "skeleton world" space. Not Unity world space.
If pos is a Unity world position, you need to transform to skeleton space.
You can do that by using the Transform or RectTransform of the SkeletonAnimation or SkeletonGraphic.
See:
https://docs.unity3d.com/ScriptReference/Transform.TransformPoint.html
https://docs.unity3d.com/ScriptReference/Transform.InverseTransformPoint.html
Thank you for your reply.
SpineAnimation is type of SkeletonGraphic
Yes, pos is mouse pointer is unity world
I tried:
Vector3 UnityToSpineWorld= SpineAnimation.rectTransform.TransformPoint(pos);
bone.worldX = UnityToSpineWorld.x;
bone.worldY = UnityToSpineWorld.y;
Now the bone moves very slowly. like in a tiny world.
I also tried, InverseTransformPoint, but it's not our case and it moves too fast that u can't see it.
Did i miss something?
Are you sure your position isn't screen space?
Input.mousePosition is screen space.
Also note that with UI, the skeleton may be subject to your Canvas' scale (referencePixelsPerUnit).
The canvas referencePixelsPerUnit is 100
While in SkeletonData the scale is set to 0.015 .
I modified SkeletonDate scale back to 0.01 to fit referencePixelsPerUnit
I am not using mousePosition, but i do get screen space.
Still same result.
All i am trying to do is to be able to "drag" with mouse one of the bones so i can move it to other place on the screen.
Issue is that i do not drag bone directly, i use an empty image with rigidbody2D and collider behind the bone and i detect with it that it gets dragged and try to position the bone into that blank image position .
Using:
draggingObject.GetComponent<Rigidbody2D>().MovePosition(pos);
After that i send single to the bone to position it self based on the position of the draggable blank image.
It seems impossible to sync them together. but i guess i am doing something wrong
This really stuck my project.
Alternative solution would be, is to have a way to get the bone sprite, so i can attach it to the unity rigidbody2D sprite and somehow make the bone invisible.
I tried this and it works just fine.
[SpineBone]
public string boneName;
public Transform transformToFollow;
public Canvas canvas;
void Start () {
var skeletonGraphic = GetComponent<SkeletonGraphic>();
if (skeletonGraphic == null) return;
// Ensure correct script execution.
skeletonGraphic.UpdateComplete += FollowTransform;
}
// Only sets the target bone's position. Does not propagate it down the hierarchy.
void FollowTransform (ISkeletonAnimation animated) {
var skeleton = animated.Skeleton;
if (skeleton == null) return;
var bone = skeleton.FindBone(boneName);
if (bone == null) return;
Vector2 transformSpacePosition = this.transform.InverseTransformPoint(transformToFollow.position) / canvas.referencePixelsPerUnit;
bone.worldX = transformSpacePosition.x;
bone.worldY = transformSpacePosition.y;
}
I'm using an existing Transform to get a Transform.position to ensure that the position we're feeding into it is actually in Unity world space.
You have to ensure the same in your case, regardless of where you get your input from.
Hello,
Thank you! I managed to make it work.
I believe the main issue was that camera /canvas and spine was not scaled/positioned correctly. I tried to keep zeroed values in the positiones in them and it worked.
Thanks!