Animation/Blend Trees? (Part 2)

Hi all!

Trying to implement animation/blend trees as mentioned in another Babylon Question post: Animation Trees?

Please view the video below at 1:15 for an animation tree demo.

This would allow us to assign one animation to some bones and another animation to the other bones. Something like this is needed to handle situations like a player jumping while transitioning from reloading to throwing a grenade, etc.

It was recommended in Animation Trees? to use two meshes for two skeletons.

This seems difficult when using an animated mesh from Mixamo, since we have to somehow divide the mesh and animations in two.

Also, in our Babylon code, we would have to manage two meshes moving together. If the legs were to crouch, we would have to move the torso, head, and arms the right amount down according to the legs crouch animation for every keyframe.

I tried experimenting in the Playground: https://playground.babylonjs.com/#9VS5TT#6

Please uncomment the 'RifleIdle' line and comment the 'RifleRun' line to run the idle animation.

// ybot.animate('RifleIdle');
ybot.animate('RifleRun');

I tried splicing the bones array in the imported Skeleton. The first line is all the bones above the leg bones. The second line is all the leg bones.

// ybot.skeleton.bones.splice(57); // head, torso, arm bones
// ybot.skeleton.bones.splice(1, 56); // leg bones

However, when uncommenting these lines, the mesh and animation becomes distorted…

ybot.skeleton.bones.splice(57); // head, torso, arm bones uncommented:


Note: Animation seems okay, but parts of leg mesh completely gone.

ybot.skeleton.bones.splice(1, 56); // leg bones uncommented:


Note: The SkeletonViewer leg bones green outline looks fine, but leg mesh completely gone, and head, torso, arm mesh shouldn’t be moving as much.

Goal: Have RifleIdle animation play for head, torso, and arms. Have RifleRun animation play for legs.

Could someone please suggest a way to use animation/blend trees without having to go into Blender and splitting our mesh and animations into two and exporting them separately to .babylon? Thank you all for your help!

Playground: https://playground.babylonjs.com/#FKKK18#5

Unsure how to get the hip bone of the top portion to follow the position of the hip bone of the bottom portion.

Playground: https://playground.babylonjs.com/#FKKK18#4

Kind of works when setting the position of the top portion mesh to the position of the bottom portion’s hip bone every frame.

Not ideal, since the hip bones of the top portion and bottom portion are disconnected. Ideally, we should be able to parent the hip bone of the top portion to the hip bone of the bottom portion.

The attempts below to parent bones aren’t working:

// Trying to set parent of hip bone of top portion to hip bone of bottom portion
// ybotTop.skeleton.bones[0].parent = ybotBottom.skeleton.bones[0];
// ybotTop.skeleton.bones[0].setParent(ybotBottom.skeleton.bones[0]);

Finally have something working, which may not work for models with more complex hip meshes and bones. This specific ybot model works nicely due to the simple hip, which is just a simple (grey) sphere in a groove.

Playground: https://playground.babylonjs.com/#S0VVNV#11

Edit: Moved all assets to a folder named old/, so Playground githubusercontent links were updated.

4 Likes

Love your dev logs of this one !!!

1 Like

So did you ever get blend tree working… ???

I am almost done implementing Unity Style Animation System using the new Babylon Toolkit.

My new pro version BABYLON.AnimationState script component class supports:

– Transitions And Conditions
– Unity Style Blend Trees (1D / 2D)
– Generic Skeletal Animations
– Retargeted Humanoid Animations
– Animation State Machines Parameters
– Multiple Animation Layers With Avatar Masking

Was wondering if anybody else did any of this stuff :slight_smile:

3 Likes

Hi @MackeyK24, thank you for checking in!

I wasn’t able to get blend trees working. To have blend trees working out of the box in Babylon.js may involve a lot of computation that I’m not yet familiar with. Instead, I used a workaround, which involved splitting the model into an upper and lower half, however this approach may not be robust for all model types.

Thank you for your amazing work on the BabylonJS UnityExporter :smiley: What you mentioned about BABYLON.AnimationState sounds exactly like the cutting-edge funcionality that is needed here! How could we go about implementing blend trees in Babylon using your work on BABYLON.AnimationState?

With the new Babylon Toolkit… You literally setup all those features just like you would for a native Unity project. You even use the same type runtime api to interact with you state machine

Example Script Component Update:

        protected update(): void {
            if (this.m_animator != null) {
                this.m_animator.setFloat("Speed", this.speed);
                this.m_animator.setFloat("Vert", this.vertical);
                this.m_animator.setFloat("Horz", this.horizontal);
            }
        }

Here is an example script component class that add a couple sliders for the Magnitude and Vertical and Horizontal Input.

In this example… I use Magnitude slide to update the Speed parameter on the state machine to control the blend tree for IDE, WALK AND RUN grounded motions

Babylon runtime showing blend tree

Example Script Component to interact with BABYLON.AnimationState script component … That simply sets the Speed animation state parameter using the setFloat function:

module PROJECT {
    /**
    * Babylon Script Component
    * @class MyPlayerController
    */
    export class MyPlayerController extends BABYLON.ScriptComponent {
        private speed:number = 0;
        private vertical:number = 0;
        private horizontal:number = 0;
        private botMeshName:string = "YBot";

        protected m_botmesh:BABYLON.AbstractMesh = null;
        protected m_animator:BABYLON.AnimationState = null;
        public constructor(transform: BABYLON.TransformNode, scene: BABYLON.Scene, properties: any = {}) {
            super(transform, scene, properties);
            this.botMeshName = this.getProperty("botMeshName", this.botMeshName);
            // Get BotMesh
            this.m_botmesh = this.getChildNode(this.botMeshName, BABYLON.SearchType.ExactMatch, false) as BABYLON.AbstractMesh;
            if (this.m_botmesh != null) this.m_animator = BABYLON.SceneManager.FindScriptComponent(this.m_botmesh, "BABYLON.AnimationState");
            else BABYLON.Tools.Warn("Failed to locate bot mesh: " + this.botMeshName);
        }

        protected start(): void {
            // Start render loop function
            // console.warn("Start Player Controller: " + this.transform.name);
            // console.log(this);

            const ui:BABYLON.GUI.AdvancedDynamicTexture = BABYLON.SceneManager.GetFullscreenUI(this.scene);
            var panel = new BABYLON.GUI.StackPanel();
            panel.width = "220px";
            panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
            panel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER;
            ui.addControl(panel);
        
            var header = new BABYLON.GUI.TextBlock();
            header.text = "Magnitude: 0";
            header.height = "30px";
            header.color = "white";
            panel.addControl(header); 
            var slider = new BABYLON.GUI.Slider();
            slider.color = "green";
            slider.minimum = 0;
            slider.maximum = 1;
            slider.value = 0;
            slider.height = "20px";
            slider.width = "200px";
            slider.onValueChangedObservable.add((value) => {
                this.speed = parseFloat(value.toFixed(2));
                header.text = "Magnitude: " + this.speed;
            });
            panel.addControl(slider);      
            
            var header1 = new BABYLON.GUI.TextBlock();
            header1.text = "Vertical: 0";
            header1.height = "30px";
            header1.color = "white";
            panel.addControl(header1); 
            var slider1 = new BABYLON.GUI.Slider();
            slider1.color = "green";
            slider1.minimum = -1;
            slider1.maximum = 1;
            slider1.value = 0;
            slider1.height = "20px";
            slider1.width = "200px";
            slider1.onValueChangedObservable.add((value) => {
                this.vertical = parseFloat(value.toFixed(2));
                header1.text = "Vertical: " + this.vertical;
            });
            panel.addControl(slider1);      

            var header2 = new BABYLON.GUI.TextBlock();
            header2.text = "Horizontal: 0";
            header2.height = "30px";
            header2.color = "white";
            panel.addControl(header2); 
            var slider2 = new BABYLON.GUI.Slider();
            slider2.color = "green";
            slider2.minimum = -1;
            slider2.maximum = 1;
            slider2.value = 0;
            slider2.height = "20px";
            slider2.width = "200px";
            slider2.onValueChangedObservable.add((value) => {
                this.horizontal = parseFloat(value.toFixed(2));
                header2.text = "Horizontal: " + this.horizontal;
            });
            panel.addControl(slider2);      
        }

        protected update(): void {
            if (this.m_animator != null) {
                this.m_animator.setFloat("Speed", this.speed);
                this.m_animator.setFloat("Vert", this.vertical);
                this.m_animator.setFloat("Horz", this.horizontal);
            }
        }

        protected after(): void {
            // After render loop function
        }

        protected destroy(): void {
            // Destroy component function
        }
    }
}

The new toolkit makes making game in Babylon … Just as easy as making Unity Games… Plus we can use the ENTIRE UNITY ECOSYSTEM to make our Babylon games :slight_smile:

1 Like

@MackeyK24, Wow, this is amazing! Can your new Babylon Toolkit be found here: UnityExporter/Redist at master · BabylonJS/UnityExporter · GitHub?

Agree this looks amazing @MackeyK24 !!!

1 Like

The new version not out yet… I plan on releasing with the final Babylon.JS 4.2 Release…

I hope to put out a beta build when we get to a Good Running beta build of 4.2 preview release

2 Likes

@MackeyK24, you are amazing :smiley: , your vision of exporting the entire Unity ecosystem to Babylon is crazy!

Just to clarify… Im not exporting the ENTIRE UNITY ECOSYSTEM…

But rather i am giving you the tooling you need to use the ENTIRE UNITY ECOSYSTEM via the Unity Editor (Editor Tools, Script Components, Prefabs, Extensions, Assets Store, Etc) to export GLTF 2.0 scene files that contain extra metadata … Thats what the Babylon Toolkit Editor does.

My Babylon Scene Manager Extension is where all the magic happens. Thats my Unity Style Micro Framework that parses the GLTF extra metadata that gives us all the super kool Unity style game development mechanics :slight_smile:

2 Likes

I’m also searching for a way to use animation blend trees applied only on some bones in ordre to combine animation. It’s a awesome way to limit animation works in 3D software + the weight of all animations. Most of the time it’s juste a matter of lower body and upper body combination.

Is there actually a way to do it even coding, (but i assume it could be quite time consuming) without cutting the character in two parts (this solution is not possible for my project) ?

@MackeyK24 if i understand you well, you are developing a tool to do that ? Is it a way to do that in unity and then export it to BJS, or will this be implemented directly to BJS ?
I don’t know when BJS 4.2 will be out, but a solution like the one in Unity must be awesome !

New Version it out… BTW @Thibaut

2 Likes