EDIT: It’s becoming embarrassing how often (even after days of failing) i write some verbose explanation of my problem - only to solve it within an hour of doing so.
The problem of was - my simplistic way of using translateZ to move the camera ‘where it’s looking’ was overriding the onObject if statement. I also had to call the onObject if statement before declaring camera.position.y in animate().
Pointerlockcontrols has functions called moveForward and moveRight - i brought these functions into my relevant animate statements and made the above changes. It now works as expected.
OLD QUESTION
I have a project that uses either pointer lock OR device orientation controls and a virtual joystick depending which is required (mobile/desktop).
My method of adding movement to device orientation controls was just to use if statements in my animate function like so (virtualjoystick.js was used):
if( joystick.right() ){
console.log ('move camera right')
let speed = 20; // px per second
let movement = speed * deltaTime;
camera.translateX(movement);
}
Here is my whole animate()
function animate() {
requestAnimationFrame( animate );
if ( controls.isLocked === true ) {
raycaster.ray.origin.copy( controls.getObject().position );
raycaster.ray.origin.y -= 10;
var intersections = raycaster.intersectObjects( objects );
var onObject = intersections.length > 0;
var time = performance.now();
var delta = ( time - prevTime ) / 1000;
velocity.x -= velocity.x * 10.0 * delta;
velocity.z -= velocity.z * 10.0 * delta;
velocity.y -= 9.8 * 100.0 * delta; // 100.0 = mass
direction.z = Number( moveForward ) - Number( moveBackward );
direction.x = Number( moveRight ) - Number( moveLeft );
direction.normalize(); // this ensures consistent movements in all directions
if ( moveForward || moveBackward ) velocity.z -= direction.z * 400.0 * delta;
if ( moveLeft || moveRight ) velocity.x -= direction.x * 400.0 * delta;
if ( onObject === true ) {
velocity.y = Math.max( 0, velocity.y );
canJump = true;
}
controls.moveRight( - velocity.x * delta );
controls.moveForward( - velocity.z * delta );
controls.getObject().position.y += ( velocity.y * delta ); // new behavior
if ( controls.getObject().position.y < 10 ) {
velocity.y = 0;
controls.getObject().position.y = 10;
canJump = true;
}
prevTime = time;
}
if ( dcontrols.enabled === true ) {
dcontrols.update();
let deltaTime = clock.getDelta();
raycaster.ray.origin.copy( camera.position );
raycaster.ray.origin.y -= 10;
var intersections = raycaster.intersectObjects( objects );
var onObject = intersections.length > 0;
velocity.y -= 9.8 * 100.0 * deltaTime; // 100.0 = mass
camera.position.y += ( velocity.y * deltaTime );
if( joystick.right() ){
console.log ('move camera right')
let speed = 20; // px per second
let movement = speed * deltaTime;
camera.translateX(movement);
}
if( joystick.left() ){
console.log ('move camera left')
let speed = 20; // px per second
let movement = speed * deltaTime;
camera.translateX(-movement);
}
if( joystick.up() ){
console.log ('move camera forward')
let speed = 20; // px per second
let movement = speed * deltaTime;
camera.translateZ(-movement);
}
if( joystick.down() ){
console.log ('move camera back')
let speed = 20; // px per second
let movement = speed * deltaTime;
camera.translateZ(movement);
}
if ( camera.position.y < 10 ) {
console.log ('Keep Camera Above 10')
velocity.y = 0;
camera.position.y = 10;
}
if ( onObject === true ) {
console.log ('On Object')
velocity.y = Math.max( 0, velocity.y );
}
}
renderer.render( scene, camera );
}
When in device orientation mode everything works as expected EXCEPT the IF statement that stops me falling through ‘objects’ (any geometry ‘pushed’ to ‘objects’).
if ( onObject === true ) {
console.log ('On Object')
velocity.y = Math.max( 0, velocity.y );
}
The console.log(‘on object’) reads in my console when testing - but instead of my camera/raycaster not having any force applied and standing on the objects - it continues, albeit at a slower speed to clip through said ‘objects’. Like this:
As you can see my onObject gets triggered correctly. But something is forcing the camera/raycaster through the object regardless.
Hoping that someone sees something wrong in my animate() - thanks!
New working 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;
var intersections = raycaster.intersectObjects( objects );
var onObject = intersections.length > 0;
velocity.y -= 9.8 * 100.0 * deltaTime; // 100.0 = mass
if ( onObject === true ) {
console.log ('On Object')
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 );
};
moveRight = function ( distance ) {
vec.setFromMatrixColumn( camera.matrix, 0 );
camera.position.addScaledVector( vec, distance );
};
if( joystick.right() ){
console.log ('move camera right')
let speed = 20; // px per second
let movement = speed * deltaTime;
moveRight (movement);
}
if( joystick.left() ){
console.log ('move camera left')
let speed = 20; // px per second
let movement = speed * deltaTime;
moveRight(-movement);
}
if( joystick.up() ){
console.log ('move camera forward')
let speed = 20; // px per second
let movement = speed * deltaTime;
moveForward( movement);
}
if( joystick.down() ){
console.log ('move camera back')
let speed = 20; // px per second
let movement = speed * deltaTime;
moveForward ( -movement);
}
if ( camera.position.y < 10 ) {
console.log ('Keep Camera Above 10')
velocity.y = 0;
camera.position.y = 10;
canJump = true;
}
prevTime = time;
}
renderer.render( scene, camera );
}