Is there a way to achieve a third-person viewpoint for a model in Aframe?

I need my A-frame camera positioned behind the model to operate in third-person perspective (TPP). I want the model to synchronize with the camera, rotating and moving along with it. However, I do not want the model to appear stuck on the camera when it moves up and down.

<html>

<head>
  <script src="https://aframe.io/releases/0.7.1/aframe.min.js"></script>
  <script src="https://cdn.rawgit.com/donmccurdy/aframe-extras/v3.13.1/dist/aframe-extras.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="30515642515d551d405849435953431d535f5d405f5e555e444370011e011e00">[email protected]</a>/dist/aframe-physics-components.min.js"></script>
  <script src="https://unpkg.com/aframe-event-set-component@^4.0.0/dist/aframe-event-set-component.min.js"></script>
  <script src="https://unpkg.com/super-hands@^3.0.1/dist/super-hands.min.js"></script>
</head>

<body>
  <a-scene physics="gravity: -9.8; restitution: 0.7;" antialias="true">
    <a-assets>
      <img id="ground-grass" src="grass.jpg" />
    </a-assets>
    <a-entity universal-controls="" camera kinematic-body=""
      position="-2.9021956210846644 1.5405810531492952 -3.927244596410301"></a-entity>
    <a-plane src="#ground-grass" scale="50 50 1" repeat=" 5 5 1" rotation="-90 0 0" static-body></a-plane>
    <a-box color="#AA0000" scale="2 2 2" position="-2.5 0.5 -7.5" static-body></a-box>
  </a-scene>
</body>

</html>

When I move the camera, the box should also move. Check image here

Answer №1

To easily achieve this, one simple approach is to reparent as follows:

 <!-- The default aframe camera entity -->
 <a-camera>
   <!-- Add an object with the same transform as the camera plus an offset -->
   <a-box position="0 0 -0.5"></a-box>
 </a-camera>

<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<a-scene>
  <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>

  <!-- "Player" -->
  <a-camera>
    <a-box position="0 -0.5 -0.65" scale="0.25 0.25 0.25" color="red"></a-box>
  </a-camera>

</a-scene>


A more intricate yet flexible solution involves creating a controller using JavaScript. Let's aim to:

  • Have the camera follow the box
  • Rotate the box with the camera
  • Achieve smooth rather than instant movements

This functionality can be implemented through a component like this:

<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c3a2afcbb2aeace56aa6aea5b8e1afa3a2b8a4acbd98d9c4d8c4da">[email protected]</a>/dist/aframe-orbit-controls.min.js"></script>

<script>
  AFRAME.registerComponent("follow-box", {
    schema: {
      target: {type: "selector"}
    },
    tick: (function() {
      // Initialize once
      const tmpv = new THREE.Vector3();

      return function(t, dt) {
        if (!this.data.target) return; // Ignore when no target specified
        const target = this.data.target.getObject3D("mesh"); // Obtain the mesh
        // Track the position
        const position = target.getWorldPosition(tmpv); // Get the world position
        this.el.object3D.position.lerp(tmpv, 0.5); // Linear interpolation towards the world position
      }
    })()
  })
  AFRAME.registerComponent("rotate-with-camera", {
    tick: (function() {
      // Initialize once
      const tmpq = new THREE.Quaternion();
      const tmpe = new THREE.Euler();
      
      return function(t, dt) {
        if (!this.el.sceneEl.camera) return; // Ignore when no camera available
        const cam = this.el.sceneEl.camera.el; // Get the camera entity
        cam.object3D.getWorldQuaternion(tmpq); // Get the world rotation
          tmpe.setFromQuaterion(tmpq, 'YXZ');
          // Setting attributes is necessary for wasd controls
        this.el.setAttribute("rotation", {x: 0, y: tmpe.y * 180 / Math.PI, z: 0 });
      }
    })()
  })
</script>
<a-scene>
  <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>

  <!-- Camera "rig" -->
  <a-entity follow-box="target: #player" look-controls>
    <a-entity camera position="0 1.6 2"></a-entity>
  </a-entity>

  <!-- The "player" -->
  <a-box id="player" color="red" wasd-controls="speed: 35" rotate-with-camera></a-box>
  
  <a-sky color="#ECECEC"></a-sky>
</a-scene>

Check out a live demonstration on Glitch of this concept in action within Aframe networked.


The optimal method would involve leveraging the orbit-controls, though customization might be needed for compatibility with wasd controls.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting issue in Typescript with useFieldArray relating to property name

I am encountering an issue with useFieldArray in TypeScript. The problem arises when trying to specify the controller's name as: name={test.${index}.firstname} The error message reads: controller.d.ts(18, 5): The expected type comes from property &ap ...

Take action upon being added to a collection or being observed

Consider the following scenario: I have an array called "x" and an Observable created from this array (arrObs). There is a button on the page, and when a user clicks on it, a random number is added to the array. The goal is to display the newly added value ...

Is there a way to execute two files concurrently in JavaScript using node.js?

I'm a beginner in the world of Javascript and Node.js, and I've encountered some issues while trying to test code I recently wrote. Specifically, I am attempting to test the code within a file named "compareCrowe.js" using another file named "tes ...

Is there a way to streamline the process of dragging and dropping multiple files with C# selenium automation?

I have successfully implemented code to drag and drop a single image, but I am unsure about the necessary changes needed to support multiple file uploads. Can anyone provide assistance with this? Thank you. driver.Url = "http://example.com"; IWebEleme ...

Invoke an Angular service from a separate JavaScript file

I have a few javascript and html files: User.js, index.html, Door.js I am looking to utilize a function in the User.js file. Link to my user.js file Link to my door.js file I am trying to call the getUserInfo function from User.Js within the Door.j ...

Issues with implementing Callouts CSS in Highcharts are causing complications

Currently, I am attempting to construct a callout, and I aim to format the callouts using CSS. Unfortunately, the CSS implementation seems to be malfunctioning for some unknown reason. Below is the HTML: <script src="https://code.highcharts.com/highch ...

Encountering Problem with Loading Blender Model in Three.js

I am struggling to successfully import a blender model into three.js. Here is what I have attempted so far: <script src="GLTFLoader.js"></script> // CHILDREN children = new THREE.Object3D(); // Blender Model ...

Occasionally, the function XMLHttpRequest() performs as expected while other times it may

I've encountered an issue with my XMLHttpRequest() function where it randomly works in both Chrome and IE. The function is triggered by On-click, but I'm having trouble catching the error. The only information I could gather is that readystate = ...

Error arises on Github when submitting a pull request due to a conflicted package

When facing conflicts in the package.json file while submitting a pull request, what is the best approach to resolve them? I usually attempt using git pull origin, but it tends to generate numerous merge commits. ...

Tips for passing an array of objects to a function in Angular4

I am trying to send an array of objects to a function in Angular 4 Calling the Function: this.clickCounter(this.people); My Object Array: people=[ {name:"john",mobile:"5678"}, {name:"sarah",mobile:"5678"}, {name:"chris",mobile:"5678"}, {name:"l ...

Are websites built with HTML and JavaScript considered secure in today's digital age?

In the scenario where I create a website using HTML5, Javascript, and CSS3 with no forms or input fields other than mouse clicks on links, as well as no logins, messaging, or comments - will this site still be vulnerable to attacks? Recently, my hosting s ...

Ways to resolve the array to string conversion issue in PHP

In my PHP project, I am dealing with a dynamic array and trying to store the array result in a variable. However, I encountered an error: array to string conversion while coding. <?php require_once('ag.php'); class H { var $Voltage; ...

Tips on incorporating a Google Plus +1 button in a Cordova/Ionic application

Incorporated a +1 button within my application: https://i.sstatic.net/1IHni.png The code used: <div class="g-plusone" data-size="tall" data-href="GOOGLE PLAY STORE LINK TO MY APP"></div> also executed this script: (function() { var po = ...

Troubleshooting: Dealing with Cross-Origin Resource Sharing (CORS) issue when using THREE.js and S

I am experiencing difficulty loading a JPG hosted in S3 into my three.js model as a texture. Upon encountering a CORS error in Chrome, I discovered that S3 supports CORS and implemented a permissive policy for testing during development (CORS is new to me) ...

Three.js - Display a model with material that can be visible without the need for a light source

I am currently utilizing Three.js, specifically version 71. My workflow involves creating models in Blender, exporting them as JSON files, and then using THREE.JSONLoader to incorporate these models into my scene as shown below: this.jsonLoader.load(path ...

Avoid updating the callback in every update by using React's useEffect

Is there a way to avoid continuously updating a callback in useEffect?. For instance, I am subscribed to an event with geofire, which listens for changes and receives locations. I want to update my state without subscribing every time there is an update. ...

Images in a horizontal dropdown selection menu

Currently, I have a traditional select dropdown that is data-bound with Angular. <select class="form-control" ng-model="category"> <option value="work">Work</option> <option value="home">Home</option> <option valu ...

Determine whether an input is currently in a "checked" state

I am working with this simple HTML layout: <fieldset> <input/> <label></label> <div class="toggle_box"> <div class="switch"></div> </div> </fieldset> My goal is to achieve the ...

Retrieving information from deeply nested JSON structures within React components

I am developing a web application that focuses on searching and displaying movie information. One of my challenges is accessing nested objects like "principals" from the same endpoint that contains the main object "title". Upon fetching the JSON response: ...

Why is the JavaScript function loaded through Ajax not running as expected?

I manage several websites with identical data protection policies. To streamline the process, I've created a file on a separate server that can be accessed through Ajax integration. One crucial aspect is the ability to set an opt-out option and store ...