Search code examples
aframe

A-frame repeating an entity


Hi I'm trying to create 100 boxes like: "a-box color="#999999" depth="0.5" height="2.5" width="2" position="0 1.25 -5""

at regular intervals in A-frame. Is there an easier way to do this than creating each one individually?


Solution

  • You can try out the template component, but I'd recommend to try out creating a custom component!

    You can create dynamically the <a-box>es in a custom component:

    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <script>
      // define a custom component
      AFRAME.registerComponent("foo", {
        init: function() {
          // create 25 boxes on a 10x10 grid
          for (var row = 0; row <= 5; row += 0.5) {
            for (var col = 0; col <= 5; col += 0.5) {
              var box = document.createElement("a-box");
              box.setAttribute("color", "blue")
              box.setAttribute("scale", "0.1 0.1 0.1")
              // use the column / row for the position
              box.setAttribute("position", {
                x: 2.5 - col, y: 5 - row, z: -2
              })
              this.el.appendChild(box);
            }
          }
        }
      })
    </script>
    <a-scene foo stats>
      <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
      <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
      <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
      <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
    </a-scene>


    Neat but super inefficient. Sooner then later the FPS will drop, and you may want to do this using the underlaying THREE.js API:

    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <script>
      // define a custom component
      AFRAME.registerComponent("foo", {
        init: function() {
          var geometry = new THREE.BoxGeometry(1, 1, 1);
          var material = new THREE.MeshNormalMaterial();
          
          // create 25 boxes on a 10x10 grid
          for (var row = 0; row <= 5; row += 0.5) {
            for (var col = 0; col <= 5; col += 0.5) {
              var box = new THREE.Mesh(geometry, material);
              box.scale.set(0.1, 0.1, 0.1);
              box.position.set(2.5 - col, 5 - row, -2)
              this.el.object3D.add(box);
            }
          }
        }
      })
    </script>
    <a-scene foo stats>
      <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
      <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
      <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
      <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
    </a-scene>


    Also stuff like "100" boxes sounds like Instanced Meshes. Check out the performance difference between HTML elements vs instanced meshes