3D Jumping Help

I have some trouble making my character jump. I looked all over and apparently there is literally no guides on how to make your character jump.

I first used the applyImpuse function:

if (app.keyboard.wasPressed(pc.KEY_SPACE)) {
                this.entity.rigidbody.applyImpulse(0,500,0);
            }

That did make my character jump, but it could jump in mid-air infinitely. I thought of something to check if the character is on the ground or not, but I have no idea on how to do it.

If you could, can you help me fix my code or show me a tutorial of it? Here’s my full code:

pc.script.attribute('speed', 'number', 0.09);

pc.script.create('PlayerMovement', function (app) {

    var PlayerMovement = function (entity) {
        this.entity = entity;
        
        this.eulers = new pc.Vec3 ();
    };
    
    var force = new pc.Vec3 ();
    var camera;
    var cameraScript;
    
    var origin = new pc.Vec3();
    var groundCheckRay = new pc.Vec3(0, -0.51, 0);
    var rayEnd = new pc.Vec3();
    
    var deltaTime;

    PlayerMovement.prototype = {

        initialize: function () {
            
            camera = app.root.findByName ('Camera');
            cameraScript = camera.script.CameraMovement;            
        },

        update: function (dt) {
            deltaTime = dt;
        },

        fixedUpdate: function (dt) {    
            
            
            
            var forward = this.entity.forward;
            var right = this.entity.right;
            var up = this.entity.up;

            var x = 0;
            var z = 0; 
            var y = 0;
            
            if (app.keyboard.isPressed(pc.KEY_A)) {
                x -= right.x;
                z -= right.z;
            }

            if (app.keyboard.isPressed(pc.KEY_D)) {
                x += right.x;
                z += right.z;
            }

            if (app.keyboard.isPressed(pc.KEY_W)) {
                x += forward.x;
                z += forward.z;
            }

            if (app.keyboard.isPressed(pc.KEY_S)) {
                x -= forward.x;
                z -= forward.z;
            }
           
            if (x !== 0 || z !== 0) {
                this.rotatePlayer ();
                
                x *= deltaTime;
                z *= deltaTime;
                
                force.set (x, 0, z).normalize ().scale (this.speed);

                this.entity.translate (force);
                this.entity.rigidbody.syncEntityToBody ();
            }
        },
        
        
        
        rotatePlayer: function () {
            var targetY = cameraScript.eulers.x + 180;

            var targetAng = new pc.Vec3 (0, targetY, 0);

            this.entity.setEulerAngles (targetAng);
            this.entity.rigidbody.syncEntityToBody ();
        }
    };

    return PlayerMovement;
});

Thanks!

You probably have to check for collision with ‘ground’.

That was my idea, but I don’t know how to check that. Could you help or send me a link of a tutorial?

Sure. Have you seen this one? https://developer.playcanvas.com/en/tutorials/collision-and-triggers/

pc.script.attribute('speed', 'number', 0.09);

pc.script.create('PlayerMovement', function (app) {

    var JUMP_IMPULSE = 400;
    
    var PlayerMovement = function (entity) {
        this.entity = entity;
        
        this.jumpImpulse = new pc.Vec3(0, JUMP_IMPULSE, 0);
        
        this.eulers = new pc.Vec3 ();
    };
    
    var force = new pc.Vec3 ();
    var camera;
    var cameraScript;
    
    var origin = new pc.Vec3();
    var groundCheckRay = new pc.Vec3(0, -0.6, 0);
    var rayEnd = new pc.Vec3();
    
    var deltaTime;
    
    this.onGround = true;

    PlayerMovement.prototype = {

        initialize: function () {
            
            camera = app.root.findByName ('Camera');
            cameraScript = camera.script.CameraMovement;   
        },

        update: function (dt) {
            deltaTime = dt;
              

        },
        
        fixedUpdate: function (dt) {    
            
            this._checkGround();  
            
            var forward = this.entity.forward;
            var right = this.entity.right;
            var up = this.entity.up;

            var x = 0;
            var z = 0; 
            var y = 0;
            
            if (app.keyboard.isPressed(pc.KEY_A)) {
                x -= right.x;
                z -= right.z;
            }

            if (app.keyboard.isPressed(pc.KEY_D)) {
                x += right.x;
                z += right.z;
            }

            if (app.keyboard.isPressed(pc.KEY_W)) {
                x += forward.x;
                z += forward.z;
            }

            if (app.keyboard.isPressed(pc.KEY_S)) {
                x -= forward.x;
                z -= forward.z;
            }
            
            if (app.keyboard.wasPressed(pc.KEY_SPACE)){
                this.jump();
            }
           
            if (x !== 0 || z !== 0) {
                this.rotatePlayer ();
                
                x *= deltaTime;
                z *= deltaTime;
                
                force.set (x, 0, z).normalize ().scale (this.speed);

                this.entity.translate (force);
                this.entity.rigidbody.syncEntityToBody ();
            }
        },
        
        rotatePlayer: function () {
            var targetY = cameraScript.eulers.x + 180;

            var targetAng = new pc.Vec3 (0, targetY, 0);

            this.entity.setEulerAngles (targetAng);
            this.entity.rigidbody.syncEntityToBody ();
    
        },
        
        jump: function () {
            if (this.onGround) {
                this.entity.rigidbody.activate();
                this.entity.rigidbody.applyImpulse(this.jumpImpulse, origin);
                this.onGround = false;                
            }
        },
        
        _checkGround: function () {
            console.log("Grounded!");
            var self = this;
            var pos = this.entity.getPosition();
            rayEnd.add2(pos, groundCheckRay);            
            self.onGround = false;

            app.systems.rigidbody.raycastFirst(pos, rayEnd, function (result) {
                self.onGround = true;
            });
        }
        
    };

    return PlayerMovement;
});

This is my code so far, but the _checkGround function doesn’t get called even though it is called in fixedUpdate. Can anyone help?

[quote=“hendryhu, post:1, topic:6674”]

pc.script.attribute('speed', 'number', 0.09);

pc.script.create('PlayerMovement', function (app) {

    var PlayerMovement = function (entity) {
        this.entity = entity;
        
        this.eulers = new pc.Vec3 ();
    };
    
    var force = new pc.Vec3 ();
    var camera;
    var cameraScript;
    
    var origin = new pc.Vec3();
    var groundCheckRay = new pc.Vec3(0, -0.51, 0);
    var rayEnd = new pc.Vec3();
    
    var deltaTime;

    PlayerMovement.prototype = {

        initialize: function () {
            
            camera = app.root.findByName ('Camera');
            cameraScript = camera.script.CameraMovement;            
        },

        update: function (dt) {
            deltaTime = dt;
        },

        fixedUpdate: function (dt) {    
            
            
            
            var forward = this.entity.forward;
            var right = this.entity.right;
            var up = this.entity.up;

            var x = 0;
            var z = 0; 
            var y = 0;
            
            if (app.keyboard.isPressed(pc.KEY_A)) {
                x -= right.x;
                z -= right.z;
            }

            if (app.keyboard.isPressed(pc.KEY_D)) {
                x += right.x;
                z += right.z;
            }

            if (app.keyboard.isPressed(pc.KEY_W)) {
                x += forward.x;
                z += forward.z;
            }

            if (app.keyboard.isPressed(pc.KEY_S)) {
                x -= forward.x;
                z -= forward.z;
            }
           
            if (x !== 0 || z !== 0) {
                this.rotatePlayer ();
                
                x *= deltaTime;
                z *= deltaTime;
                
                force.set (x, 0, z).normalize ().scale (this.speed);

                this.entity.translate (force);
                this.entity.rigidbody.syncEntityToBody ();
            }
        },
        
        
        
        rotatePlayer: function () {
            var targetY = cameraScript.eulers.x + 180;

            var targetAng = new pc.Vec3 (0, targetY, 0);

            this.entity.setEulerAngles (targetAng);
            this.entity.rigidbody.syncEntityToBody ();
        }
    };

    return PlayerMovement;
});

[/quote]s

Hello, i hope everyone is doing fine. I am a newbie so this method may not be completely correct, but it still does the work.

//detect collision
this.entity.collision.on('collisionstart', this.onCollision, this);
moveScript.prototype.onCollision = function(result) {
    var entity = result.other;
    if (entity.rigidbody)
       //set this variable to true if entity's collison is true
       onGround = true;
};
if (app.keyboard.wasPressed(pc.KEY_SPACE)) {
                if (onGround == true) {
                this.entity.rigidbody.applyImpulse(0,500,0);
                }
};

Full Code:

pc.script.attribute('speed', 'number', 0.09);

pc.script.create('PlayerMovement', function (app) {
    var onGround = true;
    var PlayerMovement = function (entity) {
        this.entity = entity;
        
        this.eulers = new pc.Vec3 ();
    };
    
    var force = new pc.Vec3 ();
    var camera;
    var cameraScript;
    
    var origin = new pc.Vec3();
    var groundCheckRay = new pc.Vec3(0, -0.51, 0);
    var rayEnd = new pc.Vec3();
    
    var deltaTime;

    PlayerMovement.prototype = {

        initialize: function () {
            
            camera = app.root.findByName ('Camera');
            cameraScript = camera.script.CameraMovement;            
        },

        update: function (dt) {
            deltaTime = dt;
        },

        fixedUpdate: function (dt) {    
            
            
            
            var forward = this.entity.forward;
            var right = this.entity.right;
            var up = this.entity.up;

            var x = 0;
            var z = 0; 
            var y = 0;
            
            if (app.keyboard.isPressed(pc.KEY_A)) {
                x -= right.x;
                z -= right.z;
            }

            if (app.keyboard.isPressed(pc.KEY_D)) {
                x += right.x;
                z += right.z;
            }

            if (app.keyboard.isPressed(pc.KEY_W)) {
                x += forward.x;
                z += forward.z;
            }

            if (app.keyboard.isPressed(pc.KEY_S)) {
                x -= forward.x;
                z -= forward.z;
            }
           
            if (x !== 0 || z !== 0) {
                this.rotatePlayer ();
                
                x *= deltaTime;
                z *= deltaTime;
                
                force.set (x, 0, z).normalize ().scale (this.speed);

                this.entity.translate (force);
                this.entity.collision.on('collisionstart', this.onCollision, this);
                moveScript.prototype.onCollision = function(result) {
                var entity = result.other;
                if (entity.rigidbody)
                //set this variable to true if entity's collison is true
                        onGround = true;
};
if (app.keyboard.wasPressed(pc.KEY_SPACE)) {
                if (onGround == true) {
                this.entity.rigidbody.applyImpulse(0,500,0);
                }
};
                this.entity.rigidbody.syncEntityToBody ();
            }
        },
        
        
        
        rotatePlayer: function () {
            var targetY = cameraScript.eulers.x + 180;

            var targetAng = new pc.Vec3 (0, targetY, 0);

            this.entity.setEulerAngles (targetAng);
            this.entity.rigidbody.syncEntityToBody ();
        }
    };

    return PlayerMovement;
});