Skip to content

Player Rig

Built In

The player rig is pre-configured and ready to go in dlux boilerplates. You don't need to do anything to make it work.

Install

If you are starting from scratch and would like to build the player rig, you will need:

html
<html>
<head>
<script src="https://rawgit.com/donmccurdy/aframe-extras/master/dist/aframe-extras.js"></script>
<script src="https://rawgit.com/fernandojsg/aframe-teleport-controls/master/dist/aframe-teleport-controls.min.js"></script>
<script src="https://unpkg.com/aframe-aabb-collider-component@^2.2.1/dist/aframe-aabb-collider-component.min.js"></script>
<script src="https://rawgit.com/wmurphyrd/aframe-super-hands-component/master/dist/super-hands.min.js"></script>
<script src="https://unpkg.com/networked-aframe@^0.6.0/dist/networked-aframe.min.js"></script>
</head>

Setup

You can think of the player as a body that moves throughout the world and has a camera for a head.

  1. Use movement-controls, a Collection of locomotion controls, which can switch between input devices as they become active. Automatically includes the following components:
    • keyboard-controls: WASD + arrow controls for movement, and more.
    • touch-controls: Touch screen (or Cardboard button) to move forward.
    • gamepad-controls: Gamepad-based rotation and movement.
    • trackpad-controls: Trackpad-based movement.
html
<body>
<a-scene>
  <a-entity id="player"
      position="0 0 0"
      movement-controls="constrainToNavMesh: true">
    <a-entity camera id="head"
        position="0 1.6 0"
        look-controls="pointerLockEnabled: true">
      <a-cursor nav-pointer
          raycaster="objects: [nav-mesh]">
      </a-cursor>
    </a-entity>
  </a-entity>
</a-scene>
</body>
</html>
  1. Create a floor for the player using nav-mesh, covered in detail here: Navmesh
html
<a-scene>
  <a-entity gltf-model="navmesh.gltf" nav-mesh></a-entity>
  ...
  1. Add controller support for Oculus Rift, HTC Vive, and Gear VR with laser-controls and teleport-controls
html
<body>
<a-scene>
  <a-entity gltf-model="navmesh.gltf" nav-mesh></a-entity>

  <a-entity id="player"
      position="0 0 0"
      movement-controls="constrainToNavMesh: true">
    <a-entity camera id="head"
        position="0 1.6 0"
        look-controls="pointerLockEnabled: true">
      <a-cursor nav-pointer
          raycaster="objects: [nav-mesh]"></a-cursor>
    </a-entity>
    <a-entity laser-controls="hand: left;"
      teleport-controls="button: trigger; collision-entities: [nav-mesh]; cameraRig: #rig; teleportOrigin: [camera];"></a-entity>
    <a-entity laser-controls="hand: right;"
      teleport-controls="button: trigger; collision-entities: [nav-mesh]; cameraRig: #rig; teleportOrigin: [camera];" ></a-entity>
  </a-entity>
</a-scene>
</body>
</html>
  • Include the script for nav-pointer in the page head
html
<head>
...
<script>
AFRAME.registerComponent('nav-pointer', {
  init: function () {
    const el = this.el;
    // On click, send the NPC to the target location.
    el.addEventListener('click', (e) => {
      const ctrlEl = el.sceneEl.querySelector('[nav-agent]');
      ctrlEl.setAttribute('nav-agent', {
        active: true,
        destination: e.detail.intersection.point
      });
    });
    // When hovering on the nav mesh, show a green cursor.
    el.addEventListener('mouseenter', () => {
      el.setAttribute('material', {color: 'green'});
    });
    el.addEventListener('mouseleave', () => {
      el.setAttribute('material', {color: 'crimson'})
    });
 
    // Refresh the raycaster after models load.
    el.sceneEl.addEventListener('object3dset', () => {
      this.el.components.raycaster.refreshObjects();
    });
  }
});
</script>
</head>
  1. Add AABB Collider to the player to collide (in this case the class .box)
html
<a-entity id="player"
          movement-controls="constrainToNavMesh: true"
          position="7 0 -18"
          aabb-collider="objects: .box"
          networked="template:#player-template;attachTemplateToLocal:true;">
  1. Add Super Hands to the controls to grab (in this case primitives a-box)
html
<a-entity laser-controls="hand: left;"
          sphere-collider="objects: a-box" super-hands
          teleport-controls="button: trigger; collision-entities: [nav-mesh]; cameraRig: #rig; teleportOrigin: [camera];">
</a-entity>
<a-entity laser-controls="hand: right;"
          sphere-collider="objects: a-box" super-hands
          teleport-controls="button: trigger; collision-entities: [nav-mesh]; cameraRig: #rig; teleportOrigin: [camera];" >
</a-entity>
  1. Add Networked A-Frame Templates
  • Templates are defined in <a-assets>
html
<a-assets>

<!-- Templates -->

  <!-- Player -->
  <template id="player-template">
    <a-entity>
      <a-entity class="nametag" look-at="#player" text="value: Hello World; align:center;" position="0 2.5 0" rotation="0 180 0" scale="8 8 8">
      </a-entity>
    </a-entity>
  </template>

  <!-- Head -->
  <template id="head-template">
    <a-entity class="avatar" networked-audio-source>
      <a-sphere class="head"
          color="#ffffff"
          scale="0.45 0.5 0.4">
      </a-sphere>
      <a-entity class="face"
          position="0 0.05 0">
        <a-sphere class="eye"
            color="#efefef"
            position="0.16 0.1 -0.35"
            scale="0.12 0.12 0.12">
          <a-sphere class="pupil"
              color="#000"
              position="0 0 -1"
              scale="0.2 0.2 0.2">
          </a-sphere>
        </a-sphere>
        <a-sphere class="eye"
            color="#efefef"
            position="-0.16 0.1 -0.35"
            scale="0.12 0.12 0.12">
          <a-sphere class="pupil"
              color="#000"
              position="0 0 -1"
              scale="0.2 0.2 0.2">
          </a-sphere>
        </a-sphere>
      </a-entity>
    </a-entity>
  </template>

  <!-- Hand -->
  <template id="hand-template">
    <a-entity>
      <a-box scale="0.1 0.1 0.1"></a-box>
    </a-entity>
  </template>
        
</a-assets>
  • declare templates on the player rig
html
<a-entity id="player"
          movement-controls="constrainToNavMesh: true"
          position="7 0 -18"
          networked="template:#player-template;attachTemplateToLocal:true;">
  <a-entity camera id="head"
            position="0 1.6 0"
            look-controls="pointerLockEnabled: true"
            networked="template:#head-template;attachTemplateToLocal:false;">