[SOLVED] Rotating 3D characters in place

Is it possible to rotate characters in place with animations (such as turning to the left?). I don’t mean just rotating with their feet in place.

I was thinking of doing:

  1. Character has a rotation of 0,180,0 with an Idle animation
  2. Start turn-left animation with animation blending
  3. Set the character rotation to 0,270,0 as the character completes the turn-left animation
  4. Blend back to idle animation

My worry is with step 3, wouldn’t it make the character instantly rotate 90 degrees too far and then blend a whole 90 degrees back to the left-idle position?

@lwall , I am currently in a project that involves this sort of animation. Are you planning on using Mixamo animations for this experiment? I suggest you do. They can be quite helpful.

There are a couple options programmers consider when they confront this issue:

  1. They need a way to rotate gradually. This is generally done using rigidbodies and the applyTorque function.
  2. You want an animation to play for the rotation so the game looks smooth, so you can either grab the Mixamo “Turn 90 Degrees” Animation, or some programmers who are sly and sneaky and want to have things more perfect, decided to use strafing animations that can blend very well and make it look like the player is still taking the necessary steps to turn.

Basically, what I’m saying is you need to use this.entity.rigidbody.applyTorque(force) to rotate the character gradually, and use either turning animations or strafing animations for the animation. I have more examples/explanations ready if they’re needed!

Yes I’m planning to use mixamo animations, I definitely don’t want to use torque, my game is a board game like chess but with 3D characters, users will be clicking on tiles to move them and the characters are just eye candy, they don’t need collisions or physics at all.

First, mixamo turn animations aren’t in-place animations, but ignoring that problem, I still need a way to change a model’s Y rotation without having it visually affect the currently playing animation, that way I can animation blend back to a different Y rotation idle state. Is that possible?

So basically, that’s what I’m talking about when I’m saying root motion is tied heavily into this. Your best bet is, like I said, to get the “Strafe Forward Right” and “Strafe Forward Left” animations from Mixamo, mark them as “In Place”, then use those as the animations for turning. It seems to have worked rather well for me animation-wise.

If you’re unwilling to apply forces to gradually rotate, then you’d have to use a custom loop in your script’s update function. If you help me to understand your project a bit more, I can help explain and craft such a script.

I’ve set up an example project

I think even with perfectly in place animations, the problem would still happen

https://playcanvas.com/project/578540/overview/3d-animation-rotation-blending
or to directly test it (hold P to turn, let go, and you will see that it jumps)
https://launch.playcanvas.com/648136?debug=true

full script:

var Animationblending = pc.createScript('animationblending');
Animationblending.states={
    idle: { 
        animation: 'male.json' 
    },
    left_turn: { 
        animation: 'Left Turn.json' 
    }
};

// initialize code called once per entity
Animationblending.prototype.initialize = function() {
    this.blendTime=0.2;
    this.setState('idle');
    
    this.app.keyboard.on(pc.EVENT_KEYDOWN,this.keyDown,this);
    this.app.keyboard.on(pc.EVENT_KEYUP,this.keyUp,this);
};

Animationblending.prototype.setState = function(state) {
    var states=Animationblending.states;
    
    this.state=state;
    this.entity.animation.play(states[state].animation,this.blendTime);
};

Animationblending.prototype.keyDown=function(e){
      if((e.key===pc.KEY_P) && (this.state!=='left_turn')){
          this.setState('left_turn');
      }
};

Animationblending.prototype.keyUp=function(e){
    if((e.key===pc.KEY_P) && (this.state==='left_turn')){ 
        this.entity.rotate(0, 90, 0);
        this.setState('idle');
    }
};

OK I think I understand what you are saying now: use a forward facing foot moving animation, then rotate the model on the Y axis via code, and just find an animation that looks correct after all of this

That seems to have worked (hold P, then let go)

https://launch.playcanvas.com/648136?debug=true

var Animationblending = pc.createScript('animationblending');
Animationblending.states={
    idle: { 
        animation: 'male.json' 
    },
    left_turn: { 
        animation: 'Left Turn.json' 
    },
    walk_strafe_left: { 
        animation: 'Walk Strafe Left.json' 
    }
};

// initialize code called once per entity
Animationblending.prototype.initialize = function() {
    this.blendTime=0.4;
    this.setState('idle');
    
    this.app.keyboard.on(pc.EVENT_KEYDOWN,this.keyDown,this);
    this.app.keyboard.on(pc.EVENT_KEYUP,this.keyUp,this);
};

Animationblending.prototype.setState = function(state) {
    var states=Animationblending.states;
    
    this.state=state;
    this.entity.animation.play(states[state].animation,this.blendTime);
};

Animationblending.prototype.keyDown=function(e){
      if((e.key===pc.KEY_P) && (this.state!=='walk_strafe_left')){
          this.setState('walk_strafe_left');
      }
      this.entity.rotate(0, 2, 0);
};

Animationblending.prototype.keyUp=function(e){
    if((e.key===pc.KEY_P) && (this.state==='walk_strafe_left')){ 
        this.setState('idle');
    }
};

I’m glad it works! Make sure you edit your title to say [SOLVED]!