Gravity Force on Spherical Surface

Hi Everyone, I’m new in PlayCanvas and I’m looking for some guidance in how to approach the following challenge:
I’m moving a car along a spherical surface using the Keyboard Arrows, but I’m having trouble to keep the Car/entity “stick” to the ground . The Gravity from the general settings is 0 and I’m using this code to force the “Car” stay on the surface, but at some point the rotation gets crazy,

this.planet = this.app.root.findByName("FakePlanet");
var gravity = new pc.Vec3();
gravity = this.planet.getPosition().sub(this.entity.getPosition());
gravity.normalize().scale(9.8);
this.entity.rigidbody.applyForce(gravity);

Here is the link of the project: https://playcanv.as/p/WG7lDKiZ/

Thanks !

Hi @dotcomadot and welcome,

Actually I think you are doing it fine, it’s just at some point your car achieves escape velocity (much like a rocket launching in space). It manages to escape your gravitational pull and get into orbit.

So I think you just have to either limit the maximum velocity the car can achieve or increase your gravity force in relation to the velocity of your car.

2 Likes

I was also thinking maybe you could change the velocity of the car to be always the tangent of the surface :thinking:

2 Likes

Nice idea!

Thanks for your replies guys,I’ll try getting more control on the speed of the car. I think the issue comes when I’m on the bottom part of the sphere (below 0 degrees) for some reason I lose the control of the car specially with the rotation.

Here is the script to control the movement of the car:


var Vehicle = pc.createScript('vehicle');


/* Custom Attributes */
Vehicle.attributes.add('speed', {
    type: 'number',
    default: 0.2
});

Vehicle.attributes.add('target', { type: 'entity' });



Vehicle.attributes.add('rotationSpeed', {
    type: 'number',
    default: 0.2
});





// initialize code called once per entity
Vehicle.prototype.initialize = function() {
    this.target.element.text = "Use Arrow Keys on PC";
};

// update code called every frame
Vehicle.prototype.update = function(dt) {
    
    this.planet = this.app.root.findByName("FakePlanet");
    var gravity = new pc.Vec3();
    gravity = this.planet.getPosition().sub(this.entity.getPosition());
    gravity.normalize().scale(10.8);
    this.entity.rigidbody.applyForce(gravity);
   
    
    if(this.app.keyboard.isPressed(pc.KEY_UP)){  
        this.impulse = new pc.Vec3();     
        this.impulse.copy(this.entity.forward).scale(-this.speed);   
        this.entity.rigidbody.applyImpulse(this.impulse);   
        
    }

    if(this.app.keyboard.isPressed(pc.KEY_DOWN)){ 
        this.backForce = new pc.Vec3();
        this.backForce = this.entity.forward.clone().scale(this.speed);
        this.entity.rigidbody.applyImpulse(this.backForce); 

    }  

    if(this.app.keyboard.isPressed(pc.KEY_RIGHT)){  
        this.entity.rigidbody.applyTorque(0, this.rotationSpeed * -1, 0);
    
    }

    if(this.app.keyboard.isPressed(pc.KEY_LEFT)){  
        this.entity.rigidbody.applyTorque(0, this.rotationSpeed, 0);

    }  


    if (this.app.keyboard.wasPressed(pc.KEY_R) ) {
  
           this.reset();
    }
       
    
    

    if(!this.entity.rigidbody.isActive()){

        var rotation = this.entity.getLocalRotation();
        var zAngle = Math.abs(rotation.z * pc.math.RAD_TO_DEG);
        var xAngle = Math.abs(rotation.x * pc.math.RAD_TO_DEG);
        if(zAngle > 10 || xAngle > 10){
            this.reset();
        }
    }
    
    
    
};



Vehicle.prototype.reset = function () {
    this.entity.setPosition(0,0,0);
    this.entity.setLocalEulerAngles(0, 0, 0);
    this.entity.rigidbody.teleport(0, 2, 0);
    this.entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
    this.entity.rigidbody.angularVelocity = pc.Vec3.ZERO;  
};