A-Frame VR Controller Support (Quest2) Tutorial
A-Frame has native support for VR controller: https://aframe.io/docs/1.4.0/introduction/interactions-and-controllers.html
However, native support does not give you customization ability. Oculus Quest2 Controller also reported not working with the default controller component; to customize support for Oculus Quest2, here is a script I made based on https://github.com/gftruj/webzamples/tree/master/aframe ; this script will give you support to move around VR scene with thumbstick and head direction:
AFRAME.registerComponent('oculus-thumbstick-controls', {
schema: {
acceleration: { default: 45 },
rigSelector: {default: "#rig"},
fly: { default: false },
controllerOriented: { default: false },
adAxis: {default: 'x', oneOf: ['x', 'y', 'z']},
wsAxis: {default: 'z', oneOf: ['x', 'y', 'z']},
enabled: {default: true},
adEnabled: {default: true},
adInverted: {default: false},
wsEnabled: {default: true},
wsInverted: {default: false}
},
init: function () {
this.easing = 1.1;
this.velocity = new THREE.Vector3(0, 0, 0);
this.tsData = new THREE.Vector2(0, 0);
this.thumbstickMoved = this.thumbstickMoved.bind(this)
this.el.addEventListener('thumbstickmoved', this.thumbstickMoved);
},
update: function() {
this.rigElement = document.querySelector(this.data.rigSelector)
},
tick: function (time, delta) {
if (!this.el.sceneEl.is('vr-mode')) return;
var data = this.data;
var el = this.rigElement
var velocity = this.velocity;
//console.log("here", this.tsData, this.tsData.length())
if (!velocity[data.adAxis] && !velocity[data.wsAxis] && !this.tsData.length()) { return; }
// Update velocity.
delta = delta / 1000;
this.updateVelocity(delta);
if (!velocity[data.adAxis] && !velocity[data.wsAxis]) { return; }
// Get movement vector and translate position.
el.object3D.position.add(this.getMovementVector(delta));
},
updateVelocity: function (delta) {
var acceleration;
var adAxis;
var adSign;
var data = this.data;
var velocity = this.velocity;
var wsAxis;
var wsSign;
const CLAMP_VELOCITY = 0.00001;
adAxis = data.adAxis;
wsAxis = data.wsAxis;
// If FPS too low, reset velocity.
if (delta > 0.2) {
velocity[adAxis] = 0;
velocity[wsAxis] = 0;
return;
}
// https://gamedev.stackexchange.com/questions/151383/frame-rate-independant-movement-with-acceleration
var scaledEasing = Math.pow(1 / this.easing, delta * 60);
// Velocity Easing.
if (velocity[adAxis] !== 0) {
velocity[adAxis] = velocity[adAxis] * scaledEasing;
}
if (velocity[wsAxis] !== 0) {
velocity[wsAxis] = velocity[wsAxis] * scaledEasing;
}
// Clamp velocity easing.
if (Math.abs(velocity[adAxis]) < CLAMP_VELOCITY) { velocity[adAxis] = 0; }
if (Math.abs(velocity[wsAxis]) < CLAMP_VELOCITY) { velocity[wsAxis] = 0; }
if (!data.enabled) { return; }
// Update velocity using keys pressed.
acceleration = data.acceleration;
if (data.adEnabled && this.tsData.x) {
adSign = data.adInverted ? -1 : 1;
velocity[adAxis] += adSign * acceleration * this.tsData.x * delta;
}
if (data.wsEnabled) {
wsSign = data.wsInverted ? -1 : 1;
velocity[wsAxis] += wsSign * acceleration * this.tsData.y * delta;
}
},
getMovementVector: (function () {
var directionVector = new THREE.Vector3(0, 0, 0);
var rotationEuler = new THREE.Euler(0, 0, 0, 'YXZ');
return function (delta) {
var rotation = this.el.sceneEl.camera.el.object3D.rotation
var velocity = this.velocity;
var xRotation;
directionVector.copy(velocity);
directionVector.multiplyScalar(delta);
// Absolute.
if (!rotation) { return directionVector; }
xRotation = this.data.fly ? rotation.x : 0;
// Transform direction relative to heading.
rotationEuler.set(xRotation, rotation.y, 0);
directionVector.applyEuler(rotationEuler);
return directionVector;
};
})(),
thumbstickMoved: function (evt) {
this.tsData.set(evt.detail.x, evt.detail.y);
},
remove: function () {
this.el.removeEventListener('thumbstickmoved', this.thumbstickMoved);
}
Basic usage
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="https://gftruj.github.io/webzamples/aframe/controls/oculus-thumbstick-controls.js"></script>
<a-scene>
<!-- Camera + controllers rig -->
<a-entity id="rig">
<a-camera position="0 1.6 0"></a-camera>
<a-entity oculus-touch-controls="hand: left" ></a-entity>
<a-entity oculus-touch-controls="hand: right" oculus-thumbstick-controls></a-entity>
</a-entity>
</a-scene>
Properties