diff --git a/src/components/audio-feedback.js b/src/components/audio-feedback.js
index 29aafcdc45bd1fb8838b4824a9c75f1c2f471c9e..6e6ea781364391ccc9361402dd6e168e3eb5dbfe 100644
--- a/src/components/audio-feedback.js
+++ b/src/components/audio-feedback.js
@@ -77,6 +77,7 @@ AFRAME.registerComponent("scale-audio-feedback", {
   },
 
   onAudioFrequencyChange(e) {
+    if (!this.el.object3D.visible) return;
     const { minScale, maxScale } = this.data;
     this.el.object3D.scale.setScalar(minScale + (maxScale - minScale) * e.detail.volume / 255);
   }
diff --git a/src/components/bone-visibility.js b/src/components/bone-visibility.js
new file mode 100644
index 0000000000000000000000000000000000000000..6f6f1a53e6f3eb464561ea91741d6d09e33a093f
--- /dev/null
+++ b/src/components/bone-visibility.js
@@ -0,0 +1,16 @@
+AFRAME.registerComponent("bone-visibility", {
+  tick() {
+    const { visible } = this.el.object3D;
+
+    if (this.lastVisible !== visible) {
+      if (visible) {
+        this.el.object3D.scale.set(1, 1, 1);
+      } else {
+        // Three.js doesn't like updating matrices with 0 scale, so we set it to a near zero number.
+        this.el.object3D.scale.set(0.00000001, 0.00000001, 0.00000001);
+      }
+
+      this.lastVisible = visible;
+    }
+  }
+});
diff --git a/src/components/ik-controller.js b/src/components/ik-controller.js
index 4fd89465e1d4ce97c24276b5d23d89eda5a25163..3fffb26668251905f25faf1876c175b12f7c21d7 100644
--- a/src/components/ik-controller.js
+++ b/src/components/ik-controller.js
@@ -1,5 +1,4 @@
 const { Vector3, Quaternion, Matrix4, Euler } = THREE;
-
 AFRAME.registerComponent("ik-root", {
   schema: {
     camera: { type: "string", default: ".camera" },
@@ -67,16 +66,12 @@ AFRAME.registerComponent("ik-controller", {
 
     this.hands = {
       left: {
-        lastVisible: true,
         rotation: new Matrix4().makeRotationFromEuler(new Euler(-Math.PI / 2, Math.PI / 2, 0))
       },
       right: {
-        lastVisible: true,
         rotation: new Matrix4().makeRotationFromEuler(new Euler(Math.PI / 2, Math.PI / 2, 0))
       }
     };
-
-    this.headLastVisible = true;
   },
 
   update(oldData) {
@@ -180,14 +175,6 @@ AFRAME.registerComponent("ik-controller", {
 
     this.updateHand(this.hands.left, leftHand, leftController);
     this.updateHand(this.hands.right, rightHand, rightController);
-
-    if (head.object3D.visible) {
-      if (!this.headLastVisible) {
-        head.object3D.scale.set(1, 1, 1);
-      }
-    } else if (this.headLastVisible) {
-      head.object3D.scale.set(0.0000001, 0.0000001, 0.0000001);
-    }
   },
 
   updateHand(handState, hand, controller) {
@@ -195,11 +182,8 @@ AFRAME.registerComponent("ik-controller", {
     const handMatrix = handObject3D.matrix;
     const controllerObject3D = controller.object3D;
 
+    handObject3D.visible = controllerObject3D.visible;
     if (controllerObject3D.visible) {
-      if (!handState.lastVisible) {
-        handObject3D.scale.set(1, 1, 1);
-        handState.lastVisible = true;
-      }
       handMatrix.multiplyMatrices(this.invRootToChest, controllerObject3D.matrix);
 
       const handControls = controller.components["hand-controls2"];
@@ -212,11 +196,6 @@ AFRAME.registerComponent("ik-controller", {
 
       handObject3D.position.setFromMatrixPosition(handMatrix);
       handObject3D.rotation.setFromRotationMatrix(handMatrix);
-    } else {
-      if (handState.lastVisible) {
-        handObject3D.scale.set(0.0000001, 0.0000001, 0.0000001);
-        handState.lastVisible = false;
-      }
     }
   }
 });
diff --git a/src/hub.html b/src/hub.html
index db3178d5d8987d913914530096386fe60b83707d..86396dd70ca446366276624ecb6fcf4f9a3194ca 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -21,6 +21,7 @@
         networked-scene="adapter: janus; audio: true; debug: true; connectOnLoad: false;"
         physics
         mute-mic="eventSrc: a-scene; toggleEvents: action_mute"
+        personal-space-bubble="debug: false;"
 
         app-mode-input-mappings="modes: default, hud; actionSets: default, hud;"
         >
@@ -130,21 +131,26 @@
                              </a-entity>
                         </template>
 
+                        <template data-selector=".Chest">
+                            <a-entity personal-space-invader="radius: 0.2" bone-visibility></a-entity>
+                        </template>
+
                         <template data-selector=".Head">
                             <a-entity
                                 networked-audio-source
                                 networked-audio-analyser
-                                personal-space-invader
+                                personal-space-invader="radius: 0.15"
+                                bone-visibility
                             >
                             </a-entity>
                         </template>
 
                         <template data-selector=".LeftHand">
-                            <a-entity personal-space-invader ></a-entity>
+                            <a-entity personal-space-invader="radius: 0.1" bone-visibility></a-entity>
                         </template>
 
                         <template data-selector=".RightHand">
-                            <a-entity personal-space-invader ></a-entity>
+                            <a-entity personal-space-invader="radius: 0.1" bone-visibility></a-entity>
                         </template>
                     </a-entity>
                 </a-entity>
@@ -233,7 +239,7 @@
                 class="camera"
                 camera
                 position="0 1.6 0"
-                personal-space-bubble
+                personal-space-bubble="radius: 0.4"
                 look-controls
             ></a-entity>
 
@@ -281,11 +287,11 @@
                 </template>
 
                 <template data-selector=".Head">
-                    <a-entity visible="false"></a-entity>
+                    <a-entity visible="false" bone-visibility></a-entity>
                 </template>
 
                 <template data-selector=".LeftHand">
-                    <a-entity>
+                    <a-entity bone-visibility>
                         <a-entity
                             id="watch"
                             gltf-model-plus="src: #watch-model"
@@ -304,7 +310,7 @@
                 </template>
 
                 <template data-selector=".RightHand">
-                    <a-entity>
+                    <a-entity bone-visibility>
                         <a-entity
                             event-repeater="events: action_grab, action_release; eventSource: #player-right-controller"
                             static-body="shape: sphere; sphereRadius: 0.02"
diff --git a/src/hub.js b/src/hub.js
index 81bab1168863396dd45b98c274a54403d09197d1..05139629a35113bd4555b77eb6db2faef9a73a75 100644
--- a/src/hub.js
+++ b/src/hub.js
@@ -23,6 +23,7 @@ import "./components/wasd-to-analog2d"; //Might be a behaviour or activator in t
 import "./components/mute-mic";
 import "./components/audio-feedback";
 import "./components/bone-mute-state-indicator";
+import "./components/bone-visibility";
 import "./components/in-world-hud";
 import "./components/virtual-gamepad-controls";
 import "./components/ik-controller";
diff --git a/src/systems/personal-space-bubble.js b/src/systems/personal-space-bubble.js
index e696705e138159a67c79e9707fe97bada64a9a58..1077e7af66785f5944adbbaf2cb5e3bbd1b73732 100644
--- a/src/systems/personal-space-bubble.js
+++ b/src/systems/personal-space-bubble.js
@@ -2,6 +2,10 @@ const invaderPos = new AFRAME.THREE.Vector3();
 const bubblePos = new AFRAME.THREE.Vector3();
 
 AFRAME.registerSystem("personal-space-bubble", {
+  schema: {
+    debug: { default: false }
+  },
+
   init() {
     this.invaders = [];
     this.bubbles = [];
@@ -53,26 +57,48 @@ AFRAME.registerSystem("personal-space-bubble", {
 
       bubblePos.setFromMatrixPosition(bubble.object3D.matrixWorld);
 
-      const radius = bubble.components["personal-space-bubble"].data.radius;
-      const radiusSquared = radius * radius;
+      const bubbleRadius = bubble.components["personal-space-bubble"].data.radius;
 
       // Hide the invader if inside the bubble
       for (let j = 0; j < this.invaders.length; j++) {
         const invader = this.invaders[j];
+        const invaderRaidus = invader.components["personal-space-invader"].data.radius;
 
         invaderPos.setFromMatrixPosition(invader.object3D.matrixWorld);
 
-        const distanceSquared = bubblePos.distanceTo(invaderPos);
+        const distanceSquared = bubblePos.distanceToSquared(invaderPos);
+        const radius = bubbleRadius + invaderRaidus;
 
-        invader.object3D.visible = distanceSquared > radiusSquared;
+        invader.object3D.visible = distanceSquared > radius * radius;
       }
     }
   }
 });
 
+function createSphereGizmo(radius) {
+  const geometry = new THREE.SphereBufferGeometry(radius, 10, 10);
+  const wireframe = new THREE.WireframeGeometry(geometry);
+  const line = new THREE.LineSegments(wireframe);
+  line.material.opacity = 0.5;
+  line.material.transparent = true;
+  return line;
+}
+
 AFRAME.registerComponent("personal-space-invader", {
+  schema: {
+    radius: { type: "number", default: 0.1 },
+    debug: { default: false }
+  },
   init() {
-    this.el.sceneEl.systems["personal-space-bubble"].registerInvader(this.el);
+    const system = this.el.sceneEl.systems["personal-space-bubble"];
+    system.registerInvader(this.el);
+    if (system.data.debug || this.data.debug) {
+      this.el.object3D.add(createSphereGizmo(this.data.radius));
+    }
+  },
+
+  update() {
+    this.radiusSquared = this.data.radius * this.data.radius;
   },
 
   remove() {
@@ -82,10 +108,18 @@ AFRAME.registerComponent("personal-space-invader", {
 
 AFRAME.registerComponent("personal-space-bubble", {
   schema: {
-    radius: { type: "number", default: 0.8 }
+    radius: { type: "number", default: 0.8 },
+    debug: { default: false }
   },
   init() {
     this.system.registerBubble(this.el);
+    if (this.system.data.debug || this.data.debug) {
+      this.el.object3D.add(createSphereGizmo(this.data.radius));
+    }
+  },
+
+  update() {
+    this.radiusSquared = this.data.radius * this.data.radius;
   },
 
   remove() {