diff --git a/src/components/character-controller.js b/src/components/character-controller.js
index d3e36432d93217d812e54e6a1ca9531d1bd12fb3..27cf940f485994ac83d1a727e41aa23d32464e05 100644
--- a/src/components/character-controller.js
+++ b/src/components/character-controller.js
@@ -125,23 +125,25 @@ AFRAME.registerComponent("character-controller", {
       yawMatrix.makeRotationAxis(rotationAxis, rotationDelta);
 
       // Translate to middle of playspace (player rig)
-      root.applyMatrix(transInv);
+      root.matrix.multiplyMatrices(transInv, root.matrix);
       // Zero playspace (player rig) rotation
-      root.applyMatrix(rotationInvMatrix);
+      root.matrix.multiplyMatrices(rotationInvMatrix, root.matrix);
       // Zero pivot (camera/head) rotation
-      root.applyMatrix(pivotRotationInvMatrix);
+      root.matrix.multiplyMatrices(pivotRotationInvMatrix, root.matrix);
       // Apply joystick translation
-      root.applyMatrix(move);
+      root.matrix.multiplyMatrices(move, root.matrix);
       // Apply joystick yaw rotation
-      root.applyMatrix(yawMatrix);
+      root.matrix.multiplyMatrices(yawMatrix, root.matrix);
       // Apply snap rotation if necessary
-      root.applyMatrix(this.pendingSnapRotationMatrix);
+      root.matrix.multiplyMatrices(this.pendingSnapRotationMatrix, root.matrix);
       // Reapply pivot (camera/head) rotation
-      root.applyMatrix(pivotRotationMatrix);
+      root.matrix.multiplyMatrices(pivotRotationMatrix, root.matrix);
       // Reapply playspace (player rig) rotation
-      root.applyMatrix(rotationMatrix);
+      root.matrix.multiplyMatrices(rotationMatrix, root.matrix);
       // Reapply playspace (player rig) translation
-      root.applyMatrix(trans);
+      root.matrix.multiplyMatrices(trans, root.matrix);
+
+      root.matrix.decompose(root.position, root.quaternion, root.scale);
 
       // TODO: the above matrix trnsfomraitons introduce some floating point errors in scale, this reverts them to
       // avoid spamming network with fake scale updates
diff --git a/src/components/cursor-controller.js b/src/components/cursor-controller.js
index 83aea2193fd285c04cbda8946880134dc3d9120f..e0dda6f0bce57127c09ef5580bf84a497ad2caf8 100644
--- a/src/components/cursor-controller.js
+++ b/src/components/cursor-controller.js
@@ -28,8 +28,8 @@ AFRAME.registerComponent("cursor-controller", {
     this.wasCursorHovered = false;
     this.origin = new THREE.Vector3();
     this.direction = new THREE.Vector3();
+    this.raycasterAttr = this.el.getAttribute("raycaster");
     this.controllerQuaternion = new THREE.Quaternion();
-
     this.data.cursor.setAttribute("material", { color: this.data.cursorColorUnhovered });
 
     this._handleCursorLoaded = this._handleCursorLoaded.bind(this);
@@ -45,6 +45,12 @@ AFRAME.registerComponent("cursor-controller", {
     this.setCursorVisibility(false);
   },
 
+  updateRay: function() {
+    this.raycasterAttr.origin = this.origin;
+    this.raycasterAttr.direction = this.direction;
+    this.el.setAttribute("raycaster", this.raycasterAttr, true);
+  },
+
   tick: (() => {
     const rayObjectRotation = new THREE.Quaternion();
 
@@ -63,7 +69,7 @@ AFRAME.registerComponent("cursor-controller", {
           .applyQuaternion(rayObjectRotation)
           .normalize();
         this.origin.setFromMatrixPosition(rayObject.matrixWorld);
-        this.el.setAttribute("raycaster", { origin: this.origin, direction: this.direction });
+        this.updateRay();
       }
 
       const isGrabbing = this.data.cursor.components["super-hands"].state.has("grab-start");
@@ -100,7 +106,7 @@ AFRAME.registerComponent("cursor-controller", {
     raycaster.setFromCamera(this.mousePos, camera);
     this.origin.copy(raycaster.ray.origin);
     this.direction.copy(raycaster.ray.direction);
-    this.el.setAttribute("raycaster", { origin: raycaster.ray.origin, direction: raycaster.ray.direction });
+    this.updateRay();
   },
 
   updateDistanceAndTargetType: function() {