[SOLVED] Audiosource and Rigdbody bug

Hi,
I was just working on a project using a rigidbody, collisions and now audiosources.
I never worked with audio in playcanvas before, so I just followed the tutorial until something went weird:

I am bouncing a ball off a surface using velocity, then I check for a collision with a boundaries box to reset the ball to its original position and to reset its physical values.
When the ball hits the surface I want to play a sound, now all that is working fine, but I found a weird quirk in the sound-components ‘positional’ attribute:

When positional is checked, the ball disappears into nowhere rather then resetting its own position, it end up behind the collider that is supposed to reset it, and before it finally “falls out of the scene” it triggers the collision event about 20 times.

This is the script attached to the ball:


pc.script.attribute('linear','vec3',[0,0,0]);
// linear velocity for the ball
pc.script.attribute('angular','vec3',[0,0,0]);
// angular velocity for the ball

pc.script.create('startVelocity', function (app) {
    // Creates a new StartVelocity instance
    var StartVelocity = function (entity) {
        this.entity = entity;
    };

    StartVelocity.prototype = {
        // Called once after all resources are loaded and before the first update
        initialize: function () 
        {   
            // store the original position of the ball to restore it later
            this.orgPos = new pc.Vec3();
            this.orgPos = this.entity.getPosition();
            // set up collision trigger
            this.entity.collision.on('collisionstart', this.onCollisionStart, this);
            
            // set velocity to the default and sync
            this.resetRigidbody();
        },
        
        resetRigidbody: function()
        {
            this.entity.rigidbody.linearVelocity = this.linear;
            this.entity.rigidbody.angularVelocity = this.angular;
            this.entity.rigidbody.syncEntityToBody();
        },
        
        onCollisionStart: function(result)
        {
            // if we hit one of the boundary objects (all named Respawn)
            if(result.other.name == "Respawn")
            {
                // restore the original position,
                this.entity.setPosition(this.orgPos.x,this.orgPos.y,this.orgPos.z);
                // then restore the original velocity and resync the rigidbody
                this.resetRigidbody();
                console.log("respawn "+this.entity.getPosition());
            }
            else
            {
                // if we hit anything else play a sound
                this.entity.sound.play('hit');
            }
        }
    };

    return StartVelocity;

Now my guess is that the positional attribute of the sound component is somehow messing up the rigidbody- or the entity-position, thus resulting in the ball respawning at the same position it collided and then slowly falling out of the collider while still respawning

Is this a bug, or am I missing a function to sync the audio source with the entity or something like this?

Thanks in advance for any help

Hi,

There is a bug in your code. Instead of

this.orgPos = this.entity.getPosition(); 

do

this.orgPos = this.entity.getPosition().clone();

Or since you already initialize orgPos to a new pc.Vec3 above that line you can also do

this.orgPos.copy(this.entity.getPosition());

Also syncEntityToBody is an internal method you should use rigidbody.teleport instead. See here:

Hi @vaios ,
thanks,
that worked, but I would have a few questions regarding these approaches:

Why is it that entity.getPosition() doesn’t return a new pc.Vec3 itself?
Would it not be safer and also handier to return an already copied or cloned value instead of returning a reference to the position vector?
If I understand this correctly it is now possible to do this: this.entity.getPosition().x = 1234;
… which might lead to undesired results… if getPosition would return a new Vec3 already, then the above had no influence on the entity at least.

And the function “syncEntityToBody” is used in this tutorial about collisions, therefore I thought it would be the better way to do this…

Finally, why is the teleport function split into several different functions enummerated like ^2, ^3 btw? Would it not be possible to merge all of these into a single “overloaded” function by checking for the amount of arguments passed to it (arguments.length) and handling the input respectively? John Resig recommends this implementation in chapter 4.4.2 of his book “Secrets of the JavaScript Ninja”

There are a lot of calls to pc.Entity#getPosition both in scripts and internally. The reason that getPosition does not return a clone every time is to avoid memory allocations whenever possible. This does lead to bugs like yours every now and then, however we find that people tend to remember to do this if they need to after a while. You don’t always need a clone, only when you are storing initial positions for example like you do.

There are some outdated tutorials we need to update. Sorry about that.

There is only one teleport function. The documentation just shows them that way to show all different variations for the arguments.