This part of my animate() causes 17fps

I have been commenting out my project bit by bit to work out why I could only get 17fps on an iPhone 7 - it turns out this part of my animate function is the issue.

animate()
if ( dcontrols.enabled === true ) {

                

        dcontrols.update();

        var time = performance.now();

        var delta = ( time - prevTime ) / 1000;

        var deltaTime = clock.getDelta();

        

        raycaster.ray.origin.copy( camera.position );

        raycaster.ray.origin.y -= 10;

        forwardRaycaster.ray.origin.copy( camera.position );

        forwardRaycaster.ray.origin.y -= 10;

        forwardRaycaster.ray.origin.z -=10;

        forwardRaycaster.ray.direction.set( 0,0,-1 ).unproject( camera ).sub( camera.position ).normalize();

        /* forwardRaycaster.setFromCamera({x:0,y:0},camera) */

        

        backwardRaycaster.ray.origin.copy( camera.position );

        backwardRaycaster.ray.origin.y -= 10;

        backwardRaycaster.ray.origin.z +=10;

        backwardRaycaster.ray.direction.set( 0,0,1 ).unproject( camera ).sub( camera.position ).normalize();

        /* backwardRaycaster.setFromCamera({x:0,y:0},camera); */

        horizontalRaycaster.ray.origin.copy( camera.position );

        horizontalRaycaster.ray.origin.y -= 10;

        horizontalRaycaster.ray.origin.x -=10;

        horizontalRaycaster.ray.direction.set( -1,0,0 ).unproject( camera ).sub( camera.position ).normalize();

        /* horizontalRaycaster.setFromCamera({x:0,y:0},camera); */

        rightHorizontalRaycaster.ray.origin.copy( camera.position );

        rightHorizontalRaycaster.ray.origin.y -= 10;

        rightHorizontalRaycaster.ray.origin.x +=10;

        rightHorizontalRaycaster.ray.direction.set( 1,0,0 ).unproject( camera ).sub( camera.position ).normalize();

        /* rightHorizontalRaycaster.setFromCamera({x:0,y:0},camera); */

                

        var intersections = raycaster.intersectObjects( objects );

        var forwardIntersections = forwardRaycaster.intersectObjects( objects );

        var backwardIntersections = backwardRaycaster.intersectObjects( objects );

        var horizontalIntersections = horizontalRaycaster.intersectObjects ( objects );

        var rightHorizontalIntersections = rightHorizontalRaycaster.intersectObjects ( objects );

        var onObject = intersections.length > 0.1;

        var forwardCollide = forwardIntersections.length > 0.1;

        var backwardCollide = backwardIntersections.length > 0.1;

        var horizontalCollide = horizontalIntersections.length > 0.1;

        var rightHorizontalCollide = rightHorizontalIntersections.length > 0.1;

        if(forwardCollide){console.log('forward colide?????????????????')}

        if(backwardCollide){console.log('backward colide?????????????????')}

        if(rightHorizontalCollide){console.log('right colide?????????????????')}

        if(horizontalCollide){console.log('left colide?????????????????')}

        

        velocity.y -= 9.8 * 100.0 * deltaTime; // 100.0 = mass

                
                

        if ( onObject === true ) {

            

        if (intersections.length < 1){

            velocity.y <= 0;

        }    

        if (intersections.length > 1){

            

            velocity.y =+ 50;

            velocity.z =+ -1;

            

        }

        

        velocity.y = Math.max( 0, velocity.y );

        canJump = true;

    }

        camera.position.y += ( velocity.y * deltaTime ); 

        

        moveForward = function ( distance ) {

            // move forward parallel to the xz-plane

            // assumes camera.up is y-up

    

            vec.setFromMatrixColumn( camera.matrix, 0 );

    

            vec.crossVectors( camera.up, vec );

    

            camera.position.addScaledVector( vec, distance );

            dcontrols.update();

    

        };

        moveRight = function ( distance ) {

            vec.setFromMatrixColumn( camera.matrix, 0 );

    

            camera.position.addScaledVector( vec, distance );

                

        };

        if ( rightHorizontalCollide == false){

                    

            if( joystick.right() ){

                console.log ('move camera right')

                let speed = 50; // px per second

                let movement = speed * deltaTime;

                moveRight (movement);

                

            }

            

        }

        if ( horizontalCollide == false){

            if( joystick.left() ){

                console.log ('move camera left')

                let speed = 50; // px per second

                let movement = speed * deltaTime;

                moveRight(-movement);

            }

        }

        if (forwardCollide == false){

            if( joystick.up() ){

                console.log ('move camera forward')

                let speed = 50; // px per second

                let movement = speed * deltaTime;

                moveForward( movement);

            }

        }

        if (backwardCollide == false) {

            if( joystick.down() ){

                console.log ('move camera back')

                let speed = 50; // px per second

                let movement = speed * deltaTime;

                moveForward ( -movement);

            }

        }

        if ( camera.position.y < 10 ) {

            

            velocity.y = 0;

            camera.position.y = 10;

            canJump = true;

        }

        prevTime = time;

    }

    stats.end();

Without this I can get 60fps. With it I get 17fps. Is that an expected tradeoff for using 5 raycasters to do collision or is my code bad/have I made an obvious error?

For some context - the code is everything that happens when the user touches the initial blocker. It initiates/updates deviceorientationcontrols and a virtual joystick controlling movement. Whilst also listening on five raycasters.

The amount of raycasters is one factor. However, it’s also important to consider the complexity of the objects you are testing. A single high-poly model can ruin your performance as well as many less complex objects. It really depends on the specific use case.

In general, using raycasting for collision detection can be unreliable and cause serious performance issue (since it can be very CPU intensive). Why? Because users often unwittingly use the geometry which is intended for rendering for collision detection too which is no good approach. It’s often better to perform intersection tests between bounding volumes like bounding spheres, AABBs, OBBs or convex hulls. Surprisingly, using the first two is sufficient for many scenarios.

Hm, ok… In my case there is only a floor in the scene for testing. But I will look into alternative colliders.

So using GLTF loader to bring in a ‘building’, and passing the mesh to ‘objects’ array for intersect test later on is ok or not ok?

Well, it depends for what you are using the array. For intensive collision detection tests, other approaches (like working with bounding volumes) are more suitable.

1 Like