Hello,
I have 2 spine projects. One contains character and second one contains vfx for this character.
I got "target" bone in on of vfx to move end position of lighting strike. It works fine in Spine I move this bone and it moves the end of lighting strike, but when I exported it to game and try to calculate this bone position everything is messed up.
I tried to get monster "x" and "y" from canvas and use comand temp1.skeleton.findBone('S3-lightning').worldToLocal({x: monsterX, y: monsterY}) , but it gives me strange positions that leads to diffrent places than monster really is.
What is "world" in this context and how I can convert monster "x" and "y" to spine local?
WorldToLocal returns random numbers with same coordinates:
Stranica: 1/1.
jakubdev
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
6 months ago
- jakubdev
- Postovi: 11
Nate
The local, parent, and world axes for translation are described here:
Tools - Spine User Guide: Translate tool
You can switch axes in Spine and look at the translation values in Spine as you move the bone around.
At runtime, if you have a world position (which is relative to the skeleton position) you need to use Bone
Tools - Spine User Guide: Translate tool
You can switch axes in Spine and look at the translation values in Spine as you move the bone around.
At runtime, if you have a world position (which is relative to the skeleton position) you need to use Bone
worldToLocal
to translate the world position into the local coordinates of the parent of the bone you want to move. Pseudo code:bone = skeleton.findBone("lightning")
position = {x: 123, y: 345} // The world position where you want the lightning bone.
bone.parent.worldToLocal(position) // Changes it to the parent's local position.
bone.x = position.x
bone.y = position.y
It wouldn't make sense for a bone to be positioned relative to itself. Bones are positioned relative to their parent, so make sure you use the parent bone. Note that the parent bone will be position = {x: 123, y: 345} // The world position where you want the lightning bone.
bone.parent.worldToLocal(position) // Changes it to the parent's local position.
bone.x = position.x
bone.y = position.y
null
if the bone is the root bone. 6 months ago
-
Nate - Postovi: 11942
jakubdev
Hey, Nate
I don't get it right.
I got a viewport that is 844x390. Spine character is {x: 87, y: 361} and from her hand, it comes lighting that needs to be targeted into an enemy that is placed {x: 422, y: 292}.
If world would be viewport. The enemy cordinates would transfer it to local with the below code.
const cords = vfx.skeleton.findBone("S3-lightning").worldToLocal({x: -335, y:0})
vfx.skeleton.findBone("S3-lightning-target").data.x = cords.x
vfx.skeleton.findBone("S3-lightning-target").data.y = cords.yDoes world mean in this context root bone? When I tried:
My take on it:
Blue dots are character/monster and vfx project roots.
Yellow dots are vfx starting point and ending.
I think vfx ending dot should be calculated by enemy.x(in that case 422) - character.x(87) - vfx.x(49) (distance from root) this value should be transfered by worldToLocal of main bone of lighting strike. Cause of lighting strike is 1288px wide by start and it doesn't show that in his bone.x this diffrence will be subtracted from worldOfLocal. I think it should be perfect ,but for some reasons it isn't.
Screenshot how it looks in game.
I don't get it right.
I got a viewport that is 844x390. Spine character is {x: 87, y: 361} and from her hand, it comes lighting that needs to be targeted into an enemy that is placed {x: 422, y: 292}.
If world would be viewport. The enemy cordinates would transfer it to local with the below code.
const cords = vfx.skeleton.findBone("S3-lightning").worldToLocal({x: -335, y:0})
vfx.skeleton.findBone("S3-lightning-target").data.x = cords.x
vfx.skeleton.findBone("S3-lightning-target").data.y = cords.y
vfx.skeleton.findBone("root").worldToLocal({x: -335, y:0}) // returns {x: -335: y: 0 }
Can I somehow calculate bone distance relative to viewport?My take on it:
Blue dots are character/monster and vfx project roots.
Yellow dots are vfx starting point and ending.
I think vfx ending dot should be calculated by enemy.x(in that case 422) - character.x(87) - vfx.x(49) (distance from root) this value should be transfered by worldToLocal of main bone of lighting strike. Cause of lighting strike is 1288px wide by start and it doesn't show that in his bone.x this diffrence will be subtracted from worldOfLocal. I think it should be perfect ,but for some reasons it isn't.
Screenshot how it looks in game.
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
6 months ago
- jakubdev
- Postovi: 11
Mario
You've set the x-coordinate on the bone data, not the bone itself. The bone data is the raw data as read from the JSON or .skel file. It serves as a basis for initializing a bone. But once a bone is initialized at runtime, that data is (mostly) never used again.
vfx.skeleton.findBone("S3-lightning-target").data.x = cords.x
should becomevfx.skeleton.findBone("S3-lightning-target").x = cords.x
6 months ago
-
Mario - Postovi: 3089
jakubdev
For some reason this don't work
only changing data affects it visually.
vfx.skeleton.findBone("S3-lightning-target").x = cords.x
only changing data affects it visually.
vfx.skeleton.findBone("S3-lightning-target").data.x = cords.x
6 months ago
- jakubdev
- Postovi: 11
Nate
The BoneData is the setup pose. All skeleton instances shared the same BoneData, so if you change it, you'll check it for all skeleton instances. It is used when resetting to the setup pose. Also, all animations are relative to the setup pose (BoneData).
When you change
Runtime Skeletons - Spine Runtimes Guide: World transforms
Rendering is done using the world transforms. If you change the local transforms and don't call
If you apply an animation after changing a Bone position and the animation keys that bone's position, then applying the animation will overwrite your position. It is common to do this every frame:
1) Apply animations.
2) Make changes to bone local transforms.
3) Call Skeleton
4) Render the skeleton.
When you change
x
or y
on the Bone, you are changing it only for that skeleton instance. Just like after applying an animation (which sets the local transforms), after you've modified a bone's local position you'll need to call Skeleton updateWorldTransform
to update the world transform for all the bones (and apply constraints). See here:Runtime Skeletons - Spine Runtimes Guide: World transforms
Rendering is done using the world transforms. If you change the local transforms and don't call
updateWorldTransform
, then you won't see your changes rendered. The last computed world transform will be used.If you apply an animation after changing a Bone position and the animation keys that bone's position, then applying the animation will overwrite your position. It is common to do this every frame:
1) Apply animations.
2) Make changes to bone local transforms.
3) Call Skeleton
updateWorldTransform
.4) Render the skeleton.
6 months ago
-
Nate - Postovi: 11942
jakubdev
Hey,
I managed to move bone directly by using bone.x and bone.y instead of bone.data.x and bone.data.y.
Had to set bone to {x:0, y:0 } in spine2d before export. For some reason bones that are already set to predefined values don't move for me in Pixi.spine that utilize yours spine runtimes. This trick managed to fix my Issues... Just for first use. Second use is random.
I tried to after first iteration:
, but this time this is completely off.
I managed to move bone directly by using bone.x and bone.y instead of bone.data.x and bone.data.y.
Had to set bone to {x:0, y:0 } in spine2d before export. For some reason bones that are already set to predefined values don't move for me in Pixi.spine that utilize yours spine runtimes. This trick managed to fix my Issues... Just for first use. Second use is random.
I tried to after first iteration:
skeleton.bones.map((bone) => bone.updateWorldTransform()
Then apply new cordinates of Another enemy withcords = skeleton.findBone('bone').worldToLocal(x:cordX, y: cordY)
Skeleton.findBone('targetingBone').x = cords.skeleton.x
Skeleton.findBone('targetingBone').y = cords.skeleton.y
Skeleton.findBone('targetingBone').x = cords.skeleton.x
Skeleton.findBone('targetingBone').y = cords.skeleton.y
, but this time this is completely off.
6 months ago
- jakubdev
- Postovi: 11
Nate
This should not be required. If you are applying an animation that keys the bone, you'll need to move your bone afterward, every frame.jakubdev je napisao/la:Had to set bone to {x:0, y:0 } in spine2d before export.
In the last code you showed, is
bone
the parent bone of targetingBone
? Also the code looks wrong for a couple reasons. Try:var parentBone = skeleton.findBone('bone');
var cords = parentBone.worldToLocal({ x: cordX, y: cordY });
var moveBone = skeleton.findBone('targetingBone');
moveBone.x = cords.x;
moveBone.y = cords.y;
var cords = parentBone.worldToLocal({ x: cordX, y: cordY });
var moveBone = skeleton.findBone('targetingBone');
moveBone.x = cords.x;
moveBone.y = cords.y;
6 months ago
-
Nate - Postovi: 11942
jakubdev
I set up once position of 'bone' and didn't had to set up it everyframe, but can't answer if its keyed as animator did Spine2d stuff.
Yes 'bone' is 'S3-Lighting' and targetingBone is 'S3-Lighting-target'.
Did change code to look more like yours without success of fixing the issue.
I managed to fix it. When I don't change 'S3-Lighting' bone position it calculates it perfectly every time. Video below:
https://drive.google.com/file/d/1DemzYFhTEFXS-gKmUDJRMt2NDmSAEDlJ/view?usp=sharing
I wrote down code that on every onComplete it reverts this value to {x: 0, y:0 } as I want to reuse once preloaded skills spritesheets of spine json and it works perfectly
Video and code below:
https://drive.google.com/file/d/1tLRzMva4WOcyxKgE71_m-rBClHudiETN/view?usp=sharing
Yes 'bone' is 'S3-Lighting' and targetingBone is 'S3-Lighting-target'.
Did change code to look more like yours without success of fixing the issue.
I managed to fix it. When I don't change 'S3-Lighting' bone position it calculates it perfectly every time. Video below:
https://drive.google.com/file/d/1DemzYFhTEFXS-gKmUDJRMt2NDmSAEDlJ/view?usp=sharing
I wrote down code that on every onComplete it reverts this value to {x: 0, y:0 } as I want to reuse once preloaded skills spritesheets of spine json and it works perfectly
Video and code below:
https://drive.google.com/file/d/1tLRzMva4WOcyxKgE71_m-rBClHudiETN/view?usp=sharing
preloadedSkills[characterData.data.name].state.onComplete = () => {
if(animationSequence.startingPoint) {
preloadedSkills[characterData.data.name].skeleton.findBone(animationSequence.startingPoint.bone).x = 0;
preloadedSkills[characterData.data.name].skeleton.findBone(animationSequence.startingPoint.bone).y = 0;
}
preloadedSkills[characterData.data.name].skeleton.bones.map((bone) => bone.updateWorldTransform());
}
What I can do to fix this issue and don't need to restart it every onComplete or even better set this position in spine2d to not calculate it here in Spine Runtimes.if(animationSequence.startingPoint) {
preloadedSkills[characterData.data.name].skeleton.findBone(animationSequence.startingPoint.bone).x = 0;
preloadedSkills[characterData.data.name].skeleton.findBone(animationSequence.startingPoint.bone).y = 0;
}
preloadedSkills[characterData.data.name].skeleton.bones.map((bone) => bone.updateWorldTransform());
}
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
6 months ago
- jakubdev
- Postovi: 11
Nate
You can look at the Spine project or JSON data and check if it is keyed. Or you can move the bone every frame, after applying animations.jakubdev je napisao/la:can't answer if its keyed as animator did Spine2d stuff.
I can't tell what is going on in the video, not what your code is doing.
You should create a skeleton with two bones and a new Unity project that displays the skeleton, then add code to move a bone. Once you get that working and understand it, you can do the same in your more complex project. It works as I showed above.
6 months ago
-
Nate - Postovi: 11942
Mark topic unread
• Stranica: 1/1.
Natrag na Runtimes
- Vremenska zona: UTC