With BVA, there’s no more skeleton or bones, only a texture with the list of transformed vertices for all the frames of the animation, so attaching a mesh to a bone won’t work.
It’s possible to get it to work to some extent, though, but it’s a bit involved.
You need a skeleton to attach the weapon to, there’s no way around that. So, a skeleton should be created for each animation (5 in the PG). As each skeleton must drive a different transform node hierarchy (actually it’s the other way around for glTF animations, but it does not change the explanation), we need to duplicate the mesh hierarchy 5 times too and connect this hierarchy to the skeleton hierarchy: the 5 skeletons and the 5 mesh hierarchies are in the skeletonForAnim and rootForAnim arrays in the PG below, respectively.
Once these objects are created, you have to retarget the animation group so that it animates the transform nodes of the corresponding rootForAnim: AnimationHelper.RetargetAnimationGroupToRoot is doing that. Also, the skeleton must be retargeted so that the bones correspond to the transform nodes animated by the animation group: AnimationHelper.RetargetSkeletonToAnimationGroup is doing that.
Now that everything is in place, you have two things to do each frame (lines 139-147):
update the bones in the skeleton with the corresponding transform node matrices: call skeleton.prepare(). That’s normally done automatically for you by the framework for all meshes that have a skeleton, but in this case we don’t have any mesh that is using the skeletons we created.
synchronize the animations of the weapons (coming from the animation groups) with the BVA => we use the current time of the BVA manager to compute the frame to go to in the animation groups
Now, the caveat…
We have a single animation group / skeleton for each animation (run, idle, …), so the weapon animation for run / idle / … is the same for all instances that uses this animation. If you use a random starting offset for a BVA animation (line 96), then the weapon animation won’t be synchronized with the BVA animation. That’s why in the PG I use a constant offset for all instances. It does not have to be 0 (as you can see in the PG), but it must be the same value for all animations of the same type (you could have a different value for the run animation vs the idle animation, for eg).
If you want to be able to use different offsets for a given animation, you will have to duplicate the animation group / skeleton so that you have as many (animation group / skeleton) as there are different offsets (for a given animation).
Another way to make it work, is by skinning the weapon instead of attaching it
Skin the weapon using the player skeleton, and weight all of its vertices to the hand bone. Then parent the weapon mesh to the player mesh. Make the weapon use the same VAT texture as the player mesh, as they have the same skeleton, and it should follow the rotation, position as well as animation.
VAT gives you performance, but increase complexity.
With items(I think in 99%), you can add bones weight via code because all vertices have 1 or 0 in most cases. Like Sword - you need to set 1 for the Hand bone and 0 for others. Same for Weapons, Helms, Boots. In some cases you can use it for Armors and Pants too(I think @oriongu in your cases you can also use it for these parts too).
To improve performace, I’m going to have to implement VAT eventually, and I was working on updating the playground, but cannot seem to get the sword attached to my player, could you have a look?
Alternatively, the weight solution you were talking about make sense, but I do not see anything about bone weight in the documentation? Would you have any playground lying around showing how I could achieve that?
The main problem is that the hierarchy of the skeleton is not the same for your character than for the character in the other PG. It seems you should use index #38 to properly attach the sword to the hand.
the order of the anims in PICKED_ANIMS should be given in the order they appear in the scene.animationGroups array
I changed how to compute the value passed to goToFrame (line 161), I’m not sure how the previous code could properly loop…
You should not retarget the anims each frame (lines 44-50), this is a process that should happen only once => I moved the block of code to line 312 in the PG below.
The purpose of the block at lines 61-66 is to play the skeletal animations exactly synchronized with the VAT frame. If you don’t do this, you will see that the sword animation is desynchronized.
For the sword anim to stop playing when the player is dead, you should just stop the animation group (line 378).
Here’s a fixed PG:
However, you will see that it does not work for the second, third, etc player deaths. That’s because you have a single skeleton for the death animation for all the (sword) players. So, the same death animation is played for all swords that are using this animation. You will have to clone the skeleton for each (sword) player to avoid this problem.
If you have a single skeleton for many meshes, it means all meshes will animate the same way (I assume you speak about skeletal animations, as VAT don’t use skeletons at replay time), that is, their animations will be synchronized (you don’t have an offset - as you have in VAT - to desynchronize skeletal animations).
I updated the PG to desynchronize the animations, so that each character instance can have its own sword animations:
Note that to show that desynchronized animations work, when you press “W”, all characters switches to the “run” animation (you can already see it with the “idle” animations, but it is harder to notice).
It required to create a skeleton per instance, and that the 4 animations be cloned and retargeted to the skeleton of each instance.
So, in the end, you end up with as many played skeletal animations as the number of instances, if each one holds a sword…
It nullifies the benefits of VAT, except that you could simplify the skeleton / the animations because you only need the bones and animation data that move the left hand. In the example PG, you only need 8 bones to get to the left hand, so you could simplify the skeleton from 41 bones to 8, as well as remove from the animations all data that don’t target these 8 bones. You could even simplify further, as you don’t really need the intermediate bones, you only need the transformation of the left hand: you could keep a single bone in the skeleton and only keep the transformations of this bone in the animation data.