AnimChannel 2 channel question

Hi Guys, If I have 2 channels with one controlling the upper body and one the lower body, which one do I assign the rootbone to? I noticed if I gave it to the lower part that some upper animations weren’t working at all. Same problem if they were both given the rootbone.

Did you animate the root bone? I use dual channels for my models but I don’t have any animation attached to the root bone. It sounds like in both the cases you mention above that the root bone is getting assigned to the bottom channel and you have some animation attached to it that the upper body is depending on.

When attaching the bones, I assume you call attachBoneFromRoot or whatever…

The way I set this up to work is…

the lower channel owns all bones from the waist down + the lower spine (the absolute parent of all upper channel bones)
the upper channel owns the mid spine bone (second in the chain of upper body bones).
This keeps both halves of the SINGLE animation sync’d

So if I run the anim “walk” on both channels (which is a single animation for the whole body), the upper and lower half stay sync’d, however if I change the upper channel to “attack” (which is also a single animation for the entire body) the body stays syn’d and runs to separate anims.

So… long story short. don’t create separate anims for the channels… plan your animations for the skeleton as a whole.

EDIT: I guess I don’t use a root bone… I use two of them.

Thats pretty much how I have it setup:
[java]

    topHalf.addFromRootBone(animControl.getSkeleton().getBone("UpperSpine"));

    lowerHalf.addBone(animControl.getSkeleton().getBone("LowerSpine"));
    lowerHalf.addFromRootBone(animControl.getSkeleton().getBone("RootBone"));
    lowerHalf.addFromRootBone(animControl.getSkeleton().getBone("R.Hip"));
    lowerHalf.addFromRootBone(animControl.getSkeleton().getBone("L.Hip")); 

[/java]

The rootbone is parent to L.hip, r.hip, and lower spine. The lower spine is parent to the upper spine. Do you see any issues with this?

For some reason attack only plays if I remove the lower half having the rootbone, but that makes some of the animations look weird that i use the rootbone on (such as going up and down when running).

Basically what you are doing in your code is adding the UpperSpine and all its children to the top half and then adding the bones LowerSpine, R.Hip, L.Hip and RootBone (and all of their children) to the lower half. RootBone is the parent of UpperSpine (RootBone -> LowerSpine -> UpperSpine). So when you add root bone you add all of the top half bones to the lower half. I believe that also removes them from the topHalf channel as well but I haven’t tried that so I don’t know. Basically, you probably want to add the “RootBone” using addBone instead of addFromRootBone.

<cite>@bgilb said:</cite> Thats pretty much how I have it setup: [java]
    topHalf.addFromRootBone(animControl.getSkeleton().getBone("UpperSpine"));

    lowerHalf.addBone(animControl.getSkeleton().getBone("LowerSpine"));
    lowerHalf.addFromRootBone(animControl.getSkeleton().getBone("RootBone"));
    lowerHalf.addFromRootBone(animControl.getSkeleton().getBone("R.Hip"));
    lowerHalf.addFromRootBone(animControl.getSkeleton().getBone("L.Hip")); 

[/java]

The rootbone is parent to L.hip, r.hip, and lower spine. The lower spine is parent to the upper spine. Do you see any issues with this?

For some reason attack only plays if I remove the lower half having the rootbone, but that makes some of the animations look weird that i use the rootbone on (such as going up and down when running).

One thing you could try is ensuring that all of your animations at least contain some key for each of these top-level bones, be it position, rotation, scale… anything to make sure that that the corresponding animation is recognized by the channel.

Okay I made some progress now by setting it up like this:
[java]
topHalf.addFromRootBone(animControl.getSkeleton().getBone(“UpperSpine”));

    lowerHalf.addBone(animControl.getSkeleton().getBone("RootBone"));
    lowerHalf.addBone(animControl.getSkeleton().getBone("LowerSpine"));
    lowerHalf.addFromRootBone(animControl.getSkeleton().getBone("R.Hip"));
    lowerHalf.addFromRootBone(animControl.getSkeleton().getBone("L.Hip"));

[/java]

The only problem now is I play the running animation for the lower and upper part seperately. This leads to it being out of sync when the upper part returns from another animation such as attack.

This is my code which decides the animation:
[java]
if(beingHit){
if(!“gethit”.equals(topHalf.getAnimationName())){
topHalf.setAnim(“gethit”);
topHalf.setSpeed(2.0f);
topHalf.setLoopMode(LoopMode.DontLoop);
}
} else if(attack){
if (!“attack”.equals(topHalf.getAnimationName())) {
topHalf.setAnim(“attack”);
topHalf.setSpeed(3.0f);
topHalf.setLoopMode(LoopMode.DontLoop);
}
} else if(((left) || (right) || (up) || (down))){
if (!“run”.equals(topHalf.getAnimationName())) {
topHalf.setAnim(“run”);
topHalf.setSpeed(2.8f);
topHalf.setLoopMode(LoopMode.Loop);
}
} else {
if (!“idle”.equals(topHalf.getAnimationName())) {
topHalf.setAnim(“idle”);
topHalf.setSpeed(0.1f);
topHalf.setLoopMode(LoopMode.Loop);
}
}

    if (((!left) &amp;&amp; (!right) &amp;&amp; (!up) &amp;&amp; (!down) &amp;&amp; (!jump))) {
        if (!"idle".equals(lowerHalf.getAnimationName())) {
            lowerHalf.setAnim("idle");
            lowerHalf.setSpeed(0.1f);
            lowerHalf.setLoopMode(LoopMode.Loop);
        }
    }

    if (left) {
        if (!"run".equals(lowerHalf.getAnimationName())) {
            lowerHalf.setAnim("run");
            lowerHalf.setSpeed(2.8f);
            lowerHalf.setLoopMode(LoopMode.Loop);
        }
    }

    if (right) {
        if (!"run".equals(lowerHalf.getAnimationName())) {
            lowerHalf.setAnim("run");
            lowerHalf.setSpeed(2.8f);
            lowerHalf.setLoopMode(LoopMode.Loop);
        }
    }
    if (up) {
        if (!"run".equals(lowerHalf.getAnimationName())) {
            lowerHalf.setAnim("run");
            lowerHalf.setSpeed(2.8f);
            lowerHalf.setLoopMode(LoopMode.Loop);
        }
    }

    if (down) {
        if (!"run".equals(lowerHalf.getAnimationName())) {
            lowerHalf.setAnim("run");
            lowerHalf.setSpeed(-2.8f);
            lowerHalf.setLoopMode(LoopMode.Loop);
        }
    }

    if ((jump &amp;&amp; up) || (jump &amp;&amp; down) || (jump &amp;&amp; left) || (jump &amp;&amp; right) || (jump)) {
        if (!"jump".equals(lowerHalf.getAnimationName())) {
            lowerHalf.setAnim("jump");
            lowerHalf.setSpeed(3f);
            lowerHalf.setLoopMode(LoopMode.DontLoop);
        }
    }

[/java]

Try:

[java]
topHalf.setTime(lowerHlf.getTime());
[/java]

When switching back to the same animation.

1 Like

That worked perfectly! Thanks a lot for the help.

1 Like