Need help with jittery character movement

I’m having an issue with character movement. We are getting this weird stuttering bug. It doesn’t happen every time, it sometimes happens from alt tabbing. Sometimes alt tabbing fixes it. But give it a try for your self and see if you can tell that it’s stuttering when moving around.

This is the script we think is causing the issue.

var CharacterMovement = pc.createScript('characterMovement');

CharacterMovement.attributes.add('moveSpeed', { type: 'number', default: 1 });
CharacterMovement.attributes.add('jumpPower', { type: 'number', default: 200.0 });

CharacterMovement.attributes.add('playerCamera', { type: 'entity' });

var _rot;

// initialize code called once per entity
CharacterMovement.prototype.initialize = function() {    
    var camera = this.app.root.findByName('Camera');
    this.cameraScript = camera.script.cameraMovement;
        
    this.app.on('player:input:direction', this.move, this);

    this.on('destroy', function() {
        this.app.off('player:input:direction', this.move, this);
    });
};

CharacterMovement.prototype.move = function(inputDirection, deltaTime) {
        
    var pos = new pc.Vec3(inputDirection.x * deltaTime, 0, inputDirection.z * deltaTime);
    pos.normalize().scale(this.moveSpeed);
    pos.add(this.entity.getPosition());

    var targetY = this.cameraScript.eulers.x;
    _rot = new pc.Vec3(0, targetY, 0);
    
    this.entity.rigidbody.teleport(new pc.Vec3(pos.x, this.entity.getPosition().y, pos.z), _rot);
};

If you want to try it out, this is the project PlayCanvas | HTML5 Game Engine

Would love any suggestions help or insight you have.

Hi @Aaron_B,

I would avoid using teleport per frame unless there is a certain reason. I can definitely see the stuttering in your solution, though I am not sure of the reason.

I’ve changed a bit your code in your InputHandler.js script to use the camera entity to grab the movement direction:

    var camera = this.app.root.findByName('Camera');
    
    if(this.app.keyboard.isPressed(pc.KEY_W)) {
        inputDirection.z += camera.forward.z;
        inputDirection.x += camera.forward.x;
    }
    
    if(this.app.keyboard.isPressed(pc.KEY_S)) {
        inputDirection.z -= camera.forward.z;
        inputDirection.x -= camera.forward.x;
    }
    
    if(this.app.keyboard.isPressed(pc.KEY_A)) {
        inputDirection.x -= camera.right.x;
        inputDirection.z -= camera.right.z;
    }
    
    if(this.app.keyboard.isPressed(pc.KEY_D)) {
        inputDirection.x += camera.right.x;
        inputDirection.z += camera.right.z;
    }

Then in your characterMovement.js script you can do simple the following to move your character smoothly enough, using the linear velocity:

CharacterMovement.prototype.move = function(inputDirection, deltaTime) {

    var force = new pc.Vec3().set(inputDirection.x, 0, inputDirection.z);
    force.scale(this.moveSpeed);
    
    this.entity.rigidbody.linearVelocity = force;
};

To avoid “slippery surfaces” behavior increase linear damping to 0.99:

image

Hope it helps.

@Leonidas

Thank you for the information, it’s incredibly smooth now. But even with the damping at .999 the character now slides when trying to simply tap the movement. Is this just simply a trade off? Or is there a way to somehow amplify the damping slightly, so we can tighten it up some more.

If you would your character to come to a complete stop when there is no input, you can do so somewhere in your input handler script. For example:

if( inputDirection.x === 0 && inputDirection.z === 0){
   this.entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
}