Problem with compound physics shapes collision count

Hello I have a problem with collision event using coumpound physics shapes.
(I’m working on a flight simulator project, and I would like to play a sound each time a tire touch the ground)

I modified the coumpound physics shapes falling chairs example to illustrate my problem https://playcanv.as/p/rmR8Byus/

When each leg of the chair hit the ground… I was expecting a “collisionstart” event… but most of the time I count only 2 collision events…

Any idea ? Thanks !

here is the script attached to the chair :

var Collision = pc.createScript('collision');

// initialize code called once per entity
Collision.prototype.initialize = function() {
    this.entity.collision.on('collisionstart', this.onCollisionStart, this);
    this.hitCount = 0;
    this.initialPos = this.entity.getPosition().clone();
    this.initialRot = this.entity.getLocalEulerAngles().clone();
};

Collision.prototype.onCollisionStart = function (result) {
    if (result.other.rigidbody) {
        this.hitCount++;
    }
};

// update code called every frame
Collision.prototype.update = function(dt) {
    pc.debug.display({hitCount:this.hitCount, notice:"press SPACE to RESET"});

    if (pc.app.keyboard.wasPressed(pc.KEY_SPACE)) {
        this.hitCount = 0;
        this.entity.rigidbody.teleport(this.initialPos,this.initialRot);
    }  
};

here is the project source code : https://playcanvas.com/editor/project/800985

I am new so i am not sure I would be able to help. But I think the thing that you are doing wrong is that you consider that all 4 legs will trigger the start collision. The thing that is happening is that your whole chair is being treated as a single rigidBody with 1 collision detection. So you are getting 2 because 1 is for the initial hit that the body hits the ground. The second hit comes when the chair bounces and hits again. If you want it to detect 4 collision on each leg then you would have to attach the collision script as well as the rigidBody and collision components to all of your legs.

I think the best way to approach that would be that add rigidBody and collision to each of the child components of the chair but not the chair entity. Then you can have another script attach to chair entity by which you can get the sum of hits of all the Childs.

1 Like

You may have more than one contact per collision event.

The contact result you get from collision start event has an array of contacts https://developer.playcanvas.com/en/api/pc.ContactResult.html#contacts

Eg it possible for all 4 legs to hit the floor in the same frame. This should give one collision event with 4 contacts.

Well, specifically for this model, it may have dozens of points. Each vertex on each leg touching the floor will generate a contact. Since the bottom of the leg consists of many vertices, each leg may have multiple contacts.

Edit:
You can see how Ammo detects contacts using the Debug Drawer. It draws the contact point normal for each vertex generating a contact. The reason the contacts change is because of the way Ammo solves the collision.
https://playcanvas.com/editor/scene/1169174

You can grab the drawer here:
https://playcanvas.com/project/744419/overview/ammo-debug-draw

2 Likes

@MHA : I tried that but it doesn’t work with coumpound physics shapes collision : if I add rigidBody & collision to the chair… the chair parts become free to move independently => the chair is broken … and reading the one of the @yaustar answer in this forum thread (https://forum.playcanvas.com/t/where-can-i-find-documentation-for-the-compound-collider/16177/5), I understand that the way the coumpound physics shapes collision works imply that you don’t add rigidbody to child physics shapes collision :

"That would be an incorrect setup as only the parent entity should be set as either a rigidBody or just a collider (trigger). The children should only have collider components that define the shape of the compound "

As @MHA mentioned, the compound collider will fire a collision start event as a single body. It means, that a new collision start event will be fired, only if the previous one ended. If the body keeps touching the floor with some part, it will not trigger new events.

Not sure if there is an easy way without some custom logic that is specific to your model. As Ammo is concerned, it is just a bunch of vertices - it will report whichever is touching the ground, but it is then up to you to decide if it is a new collision or not.

I have tried it check it if it’s right.
Link = https://playcanvas.com/editor/scene/1169259
The ground has to be kinetic rigidBody because trigger doesn’t work with static.

I just did some basic stuff but I think I might have done the thing that you want to accomplish. Tell me if it helped you. I have not made the whole chair but just 4 legs. Hope you figure out the rest if I am right.

thks @LeXXik for your project and and explanations… I understand now much more better what is happening ! thks also @MHA… I think it would solve my problem to be able to to attach the collision script to each leg… but it’s not working unfortunately :frowning:

I have modified the example project so it’s look like more what I’m looking for (I replaced the chair by an aircraft with 3 wheels. I’m will try tonight to go ahead from there !

EDIT : I ended up using old fashion height test for each wheel of the aircraft instead of collision event :

var Collision = pc.createScript('collision');


// initialize code called once per entity
Collision.prototype.initialize = function() {
    this.hitCount = 0;
    this.initialPos = this.entity.getPosition().clone();
    this.initialRot = this.entity.getEulerAngles().clone();
    
    this.tailWheelEntity = this.app.root.findByName("tail wheel");
    this.rightWheelEntity = this.app.root.findByName("right wheel");
    this.leftWheelEntity = this.app.root.findByName("left wheel");
    
    this.tailWheelOnGround = false;
    this.rightWheelOnGround = false;
    this.leftWheelOnGround = false;
    
    this.groundY = 2.04;
    this.resetSoundHeight = 0.01;

};


// update code called every frame
Collision.prototype.update = function(dt) {
    var tailHeight = this.tailWheelEntity.getPosition().y - this.groundY  + 0.1; // small wheel.... no comment;
    var rightWheelHeight = this.rightWheelEntity.getPosition().y - this.groundY;
    var leftWheelHeight = this.leftWheelEntity.getPosition().y - this.groundY;
    pc.debug.display({tailY : tailHeight,
                      rightWheelY:rightWheelHeight,
                      leftWheelY:leftWheelHeight,
                      hitCount : this.hitCount,
                      NOTICE : "Press SPACE BAR to Reset",
                      NB : "Click on screen to enable sound"});
    
    if ((tailHeight<0) && (this.tailWheelOnGround===false)) { this.tailWheelOnGround = true; this.entity.sound.play("hit"); this.hitCount++;}
    if ((tailHeight>this.resetSoundHeight) && (this.tailWheelOnGround===true)) { this.tailWheelOnGround = false;}


    if ((rightWheelHeight<0) && (this.rightWheelOnGround===false)) { this.rightWheelOnGround = true; this.entity.sound.play("hit"); this.hitCount++;}
    if ((rightWheelHeight>this.resetSoundHeight) && (this.rightWheelOnGround===true)) { this.rightWheelOnGround = false;}

    if ((leftWheelHeight<0) && (this.leftWheelOnGround===false)) { this.leftWheelOnGround = true; this.entity.sound.play("hit"); this.hitCount++;}
    if ((leftWheelHeight>this.resetSoundHeight) && (this.leftWheelOnGround===true)) { this.leftWheelOnGround = false;}
    
    //pc.debug.display({hitCount:this.hitCount, notice:"press SPACE to RESET"});

    if (pc.app.keyboard.wasPressed(pc.KEY_SPACE)) {
        this.hitCount = 0;
//        this.entity.rigidbody.teleport(this.initialPos,this.initialRot);

        var m = new pc.Mat4();
        //m.setFromEulerAngles(Math.random()*30-15, 0, Math.random()*30-15);
        this.entity.rigidbody.teleport(this.initialPos.x,this.initialPos.y,this.initialPos.z, Math.random()*30-15,0,Math.random()*30-15);
        this.entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
        this.entity.rigidbody.angularVelocity = pc.Vec3.ZERO;
    }  
};

The project is here : https://playcanvas.com/project/800985/overview/flight-simulator-alpha
… and the executable : https://playcanv.as/p/rmR8Byus/

thks for your help !

1 Like