[SOLVED] How To Make Rigidbody Move As If I'm Moving With Translate

I’ve been trying to make a Mario game, and I realized that Mario usually stops immediately after you let go of right or left in the original NES game. But Rigidbodies have more of a smooth movement. I want the Rigidbody to stop immediately after you let go of left or right. I tried using the FPS code, that seems similar to translating a rigidbody, but it doesn’t work for some reason. Here is my code:

var PlayerController = pc.createScript('playerController');

//Attributes
PlayerController.attributes.add("speed", { type: 'number', title: 'Movement Speed' });
PlayerController.attributes.add("grv", { type: 'number', title: 'Gravity' });
PlayerController.attributes.add("camera", { type: 'entity', title: 'Camera' });

//Animations
PlayerController.attributes.add("idle", { type: 'entity', title: 'Idle' });
PlayerController.attributes.add("run", { type: 'entity', title: 'Run' });

//Variables
var onGround = false;
var ysp = 0;
var goingRight = true;

// initialize code called once per entity
PlayerController.prototype.initialize = function() {
    this.app.keyboard.on(pc.EVENT_KEYDOWN, this.onKeyDown, this);
    this.app.keyboard.on(pc.EVENT_KEYUP, this.onKeyUp, this);
    this.entity.collision.on('contact', this.onContact, this);
    this.force = new pc.Vec3();
    this.idle.enabled = true;
    this.run.enabled = false;
};

// update code called every frame
PlayerController.prototype.update = function(dt) {
    this.movement(dt);  
    this.animation();
    this.flip();
};

PlayerController.prototype.movement = function(dt) {  
    var force = this.force;
    var x = 0;
    var right = this.camera.right;
    
    if (this.app.keyboard.isPressed(pc.KEY_RIGHT)) {
        x += right;
        goingRight = true;
    }  
    if (this.app.keyboard.isPressed(pc.KEY_LEFT)) {
        x -= right;
        goingRight = false;
    }
    if (this.app.keyboard.isPressed(pc.KEY_RIGHT) && this.app.keyboard.isPressed(pc.KEY_LEFT)) {
        goingRight = null;
    }
    
    force.set(x, 0, 0).normalize().scale(this.speed);
    this.entity.rigidbody.applyForce(force);
};

PlayerController.prototype.gravity = function(dt) {
    if (onGround === false) {
        this.entity.translate(0, ysp * dt, 0);
        ysp -= this.grv;
        
        if (ysp <= -6) {
            ysp = -6;
        }
    }  
    else if (onGround === true) {
        ysp = 0;
    }
};

PlayerController.prototype.onContact = function(result) {
    //Check Collision
    if (result.other.tags.has('ground')) {
        onGround = true;
    }  
    else if (result.other.tags.has('startGravity')) {
        onGround = false;
    }
};

PlayerController.prototype.animation = function() {
    if (this.app.keyboard.isPressed(pc.KEY_RIGHT) || this.app.keyboard.isPressed(pc.KEY_LEFT)) {
        this.idle.enabled = false;
        this.run.enabled = true;
    } 
    else if (goingRight === null) {
        this.idle.enabled = true;
        this.run.enabled = false;
    }
    else {
        this.idle.enabled = true;
        this.run.enabled = false;
    }
};

PlayerController.prototype.flip = function() {
    if (goingRight === true) {
        this.entity.setLocalScale(1, 1, 1);
    }      
    else if (goingRight === false) {
        this.entity.setLocalScale(-1, 1, 1);
    }
};

// swap method called for script hot-reloading
// inherit your script state here
// PlayerController.prototype.swap = function(old) { };

// to learn more about script anatomy, please read:
// http://developer.playcanvas.com/en/user-manual/scripting/

Does anyone know how to make it so that the Rigidbody stops moving immediately after you release right or left?

Link To Editor: https://playcanvas.com/editor/scene/907075

Hi @Invisible and welcome!

You can get close by playing with the friction property, in both the Player and level objects:

image

That will have the effect of rapidly decreasing velocity when the movement forces stop to be applied. But still it won’t be fully immediate.

To do that you can set directly the linear velocity of your player rigid body to be zero, as soon as he stops moving:

var linearVelocity = this.entity.rigidbody.linearVelocity;
linearVelocity.set(0, 0, 0);
this.entity.rigidbody.linearVelocity = linearVelocity;
2 Likes

It worked perfectly. Although I tried something similar before. I set the linearVelocity.x to 0 before, but then the player completely stopped moving. I think I put the code like this:

this.entity.rigidbody.linearVelocity = new pc.Vec3(0, this.entity.rigidbody.linearVelocity.y, this.entity.rigidbody.linearVelocity.z);

Was there something I did wrong previously?

Mmm, good question, not fully sure but the issue may be that you create a new pc.Vec3 object here instead of reusing the existing.

And that may break some reference that is being used internally by the physics engine.

1 Like

That’s a satisfying answer. I think using a variable that’s already established is a better way of making the player rigidbody stop immediately after letting go of right or left.

1 Like