diff --git a/package.json b/package.json
index 93154d2d912d0d40d3ff8a067326064c206d46b5..73f3ad5bba8c7896b3e30a6328d4a3fe25f86353 100644
--- a/package.json
+++ b/package.json
@@ -19,11 +19,11 @@
     "@fortawesome/fontawesome-free-solid": "^5.0.9",
     "@fortawesome/react-fontawesome": "^0.0.18",
     "aframe-billboard-component": "^1.0.0",
-    "aframe-extras": "^3.12.4",
+    "aframe-extras": "^4.0.0",
     "aframe-input-mapping-component": "https://github.com/johnshaughnessy/aframe-input-mapping-component#feature/map-to-array",
     "aframe-physics-extras": "https://github.com/infinitelee/aframe-physics-extras#fix/physics-collider-crash",
     "aframe-physics-system": "https://github.com/donmccurdy/aframe-physics-system",
-    "aframe-teleport-controls": "https://github.com/netpro2k/aframe-teleport-controls#feature/pauseable",
+    "aframe-teleport-controls": "^0.3.1",
     "aframe-xr": "github:brianpeiris/aframe-xr#3162aed",
     "classnames": "^2.2.5",
     "detect-browser": "^2.1.0",
diff --git a/src/components/character-controller.js b/src/components/character-controller.js
index 1249dff3b0fbb3231bb52bd373e6cd91b7f3a544..8da41b1a2e4bf4f3928a8f74b6a521679b11759a 100644
--- a/src/components/character-controller.js
+++ b/src/components/character-controller.js
@@ -1,5 +1,6 @@
 const CLAMP_VELOCITY = 0.01;
 const MAX_DELTA = 0.2;
+const EPS = 10e-6;
 
 // Does not have any type of collisions yet.
 AFRAME.registerComponent("character-controller", {
@@ -79,6 +80,8 @@ AFRAME.registerComponent("character-controller", {
     const rotationInvMatrix = new THREE.Matrix4();
     const pivotRotationMatrix = new THREE.Matrix4();
     const pivotRotationInvMatrix = new THREE.Matrix4();
+    const start = new THREE.Vector3();
+    let navGroup, navNode;
 
     return function(t, dt) {
       const deltaSeconds = dt / 1000;
@@ -87,6 +90,8 @@ AFRAME.registerComponent("character-controller", {
       const distance = this.data.groundAcc * deltaSeconds;
       const rotationDelta = this.data.rotationSpeed * this.angularVelocity * deltaSeconds;
 
+      start.copy(root.position);
+
       // Other aframe components like teleport-controls set position/rotation/scale, not the matrix, so we need to make sure to compose them back into the matrix
       root.updateMatrix();
 
@@ -128,9 +133,19 @@ AFRAME.registerComponent("character-controller", {
         z: root.rotation.z * THREE.Math.RAD2DEG
       });
 
-      this.el.setAttribute("position", root.position);
-
       this.pendingSnapRotationMatrix.identity(); // Revert to identity
+
+      //copied from aframe-extras movement-controls
+      const nav = this.el.sceneEl.systems.nav;
+      if (nav.navMesh && this.velocity.lengthSq() > EPS) {
+        if (!navGroup) {
+          navGroup = nav.getGroup(start);
+        }
+        navNode = navNode || nav.getNode(start, navGroup);
+        navNode = nav.clampStep(start, root.position, navGroup, navNode, root.position);
+      } else {
+        this.el.setAttribute("position", root.position);
+      }
     };
   })(),
 
diff --git a/src/components/gltf-bundle.js b/src/components/gltf-bundle.js
index 38120d8f369389995839c5eb9836e6682fc4b98f..ba6f7b3dc6d78aa08646352e49b6e3f91031056a 100644
--- a/src/components/gltf-bundle.js
+++ b/src/components/gltf-bundle.js
@@ -23,7 +23,7 @@ AFRAME.registerComponent("gltf-bundle", {
 
       const src = new URL(asset.src, this.baseURL).href;
       const gltfEl = document.createElement("a-entity");
-      gltfEl.setAttribute("gltf-model-plus", { src });
+      gltfEl.setAttribute("gltf-model-plus", { src, inflate: true });
       loaded.push(new Promise(resolve => gltfEl.addEventListener("model-loaded", resolve)));
       this.el.appendChild(gltfEl);
     }
diff --git a/src/components/gltf-model-plus.js b/src/components/gltf-model-plus.js
index 3864f9327c92ce63deddf8f08766a9316cf4a3da..d9ff8d8ff722388d3b0a63f4731d5541e91bde5e 100644
--- a/src/components/gltf-model-plus.js
+++ b/src/components/gltf-model-plus.js
@@ -127,7 +127,7 @@ const inflateEntities = function(parentEl, node) {
   const entityComponents = node.userData.components;
   if (entityComponents) {
     for (const prop in entityComponents) {
-      if (entityComponents.hasOwnProperty(prop)) {
+      if (entityComponents.hasOwnProperty(prop) && AFRAME.GLTFModelPlus.components.hasOwnProperty(prop)) {
         const { inflator, componentName } = AFRAME.GLTFModelPlus.components[prop];
 
         if (inflator) {
diff --git a/src/gltf-component-mappings.js b/src/gltf-component-mappings.js
index 7c6b6a8d8774eeeda0de6f0fb074848a5e78be51..06e81969a0f72d0d3a90ae7b247f28bf68fa2aaa 100644
--- a/src/gltf-component-mappings.js
+++ b/src/gltf-component-mappings.js
@@ -2,3 +2,5 @@ import "./components/gltf-model-plus";
 
 AFRAME.GLTFModelPlus.registerComponent("scale-audio-feedback", "scale-audio-feedback");
 AFRAME.GLTFModelPlus.registerComponent("loop-animation", "loop-animation");
+AFRAME.GLTFModelPlus.registerComponent("visible", "visible");
+AFRAME.GLTFModelPlus.registerComponent("nav-mesh", "nav-mesh");
diff --git a/src/hub.html b/src/hub.html
index 17a55076ed5f8fd37ce6d6b0d40fd0326ffd7bf9..d88ef18140a86b1173d9c1dfe68966cbd5b88283 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -135,7 +135,7 @@
             scale="2 2 2"
             class="interactable" 
             super-spawner="template: #interactable-template;" 
-            position="2.5 1.2 0" 
+            position="2.9 1.2 0" 
             body="mass: 0; type: static; shape: box;"
         ></a-entity>
 
@@ -194,7 +194,11 @@
                 class="left-controller"
                 hand-controls2="left"
                 tracked-controls
-                teleport-controls="cameraRig: #player-rig; teleportOrigin: #player-camera; button: action_teleport_"
+                teleport-controls="
+                    cameraRig: #player-rig; 
+                    teleportOrigin: #player-camera; 
+                    button: action_teleport_; 
+                    collisionEntities: #nav-mesh"
                 app-mode-toggle-playing__teleport-controls="mode: hud; invert: true;"
                 haptic-feedback
             ></a-entity>
@@ -206,7 +210,11 @@
                 class="right-controller"
                 hand-controls2="right"
                 tracked-controls
-                teleport-controls="cameraRig: #player-rig; teleportOrigin: #player-camera; button: action_teleport_"
+                teleport-controls="
+                    cameraRig: #player-rig; 
+                    teleportOrigin: #player-camera; 
+                    button: action_teleport_; 
+                    collisionEntities: #nav-mesh"
                 haptic-feedback
                 raycaster="objects:.hud; showLine: true; far: 2;"
                 cursor="fuse: false; downEvents: action_ui_select_down; upEvents: action_ui_select_up;"
diff --git a/src/hub.js b/src/hub.js
index bbf9c2b1f0680cb65874b67f426db0871aa19764..fc843649946ff6630563dfa1c1efd78e1d2b00d1 100644
--- a/src/hub.js
+++ b/src/hub.js
@@ -69,6 +69,7 @@ if (qs.quality) {
 
 import "aframe-physics-system";
 import "aframe-physics-extras";
+import "aframe-extras/src/pathfinding";
 import "super-hands";
 import "./components/super-networked-interactable";
 import "./components/networked-counter";
diff --git a/yarn.lock b/yarn.lock
index 41b0864f101f538ab31881607f082cfbc8b50cd7..76d6c651b95192f98f08e688fe9f38a529b5be4a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -160,12 +160,11 @@ aframe-billboard-component@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/aframe-billboard-component/-/aframe-billboard-component-1.0.0.tgz#10ce2482729eef7386c5844d65917581a62d3adc"
 
-aframe-extras@^3.12.4:
-  version "3.13.1"
-  resolved "https://registry.yarnpkg.com/aframe-extras/-/aframe-extras-3.13.1.tgz#f8b6ef18c29e92538d05d94913640942a307c46c"
+aframe-extras@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/aframe-extras/-/aframe-extras-4.0.0.tgz#fc851e2a1312c30a4d4addc3e0fa2dbf3e723ead"
   dependencies:
-    aframe-physics-system "^1.4.3"
-    three-pathfinding "^0.2.2"
+    three-pathfinding "^0.5.5"
 
 "aframe-input-mapping-component@https://github.com/johnshaughnessy/aframe-input-mapping-component#feature/map-to-array":
   version "0.1.2"
@@ -181,13 +180,6 @@ aframe-lerp-component@^1.1.0:
   version "0.1.2"
   resolved "https://github.com/infinitelee/aframe-physics-extras#49b2d5d3c0caac905783aee51d9e89dbdf7199b8"
 
-aframe-physics-system@^1.4.3:
-  version "1.4.3"
-  resolved "https://registry.yarnpkg.com/aframe-physics-system/-/aframe-physics-system-1.4.3.tgz#c6927e847081bfe546658314aa4c04958ef27934"
-  dependencies:
-    cannon "github:donmccurdy/cannon.js#v0.6.2-dev1"
-    three-to-cannon "^1.1.1"
-
 "aframe-physics-system@https://github.com/donmccurdy/aframe-physics-system":
   version "3.0.1"
   resolved "https://github.com/donmccurdy/aframe-physics-system#08a98a4c3d77c4c38a1fa27067aa0d894447902e"
@@ -198,9 +190,9 @@ aframe-physics-system@^1.4.3:
     three-to-cannon "^1.2.0"
     webworkify "^1.4.0"
 
-"aframe-teleport-controls@https://github.com/netpro2k/aframe-teleport-controls#feature/pauseable":
-  version "0.3.2"
-  resolved "https://github.com/netpro2k/aframe-teleport-controls#7f67003dd3bd1348357fbf89aaeed916ef2d4016"
+aframe-teleport-controls@^0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/aframe-teleport-controls/-/aframe-teleport-controls-0.3.1.tgz#7d7ef206f483ea92425a6333b0f8fb26c9596d1c"
 
 "aframe-xr@github:brianpeiris/aframe-xr#3162aed":
   version "0.0.9"
@@ -7622,11 +7614,11 @@ textextensions@2:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.2.0.tgz#38ac676151285b658654581987a0ce1a4490d286"
 
-three-pathfinding@^0.2.2:
-  version "0.2.3"
-  resolved "https://registry.yarnpkg.com/three-pathfinding/-/three-pathfinding-0.2.3.tgz#469bb26fb6b331f536c9ec88fde78e9c9219f637"
+three-pathfinding@^0.5.5:
+  version "0.5.5"
+  resolved "https://registry.yarnpkg.com/three-pathfinding/-/three-pathfinding-0.5.5.tgz#ff05a8f8cfba343b3b07c05c25d11b0d161911f8"
 
-three-to-cannon@^1.1.1, three-to-cannon@^1.2.0:
+three-to-cannon@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/three-to-cannon/-/three-to-cannon-1.2.0.tgz#92b9a756a270851aa98c3058c51ef15891507c01"