【问题标题】:Three.js lookAt function not working correctlyThree.js lookAt 功能无法正常工作
【发布时间】:2019-02-20 04:52:22
【问题描述】:

所以,我尝试使用 lookAt 函数,因为我希望僵尸走向角色。问题似乎是它甚至没有正确转动,而是在奇怪的角度上。这就是我所做的:

var pos = new THREE.Vector3(self.position.x - player.x, self.position.y, self.position.z - player.z) self.lookAt(pos)

是的,有什么问题?我有一个理论,我需要以某种方式获取玩家的相对位置,但我不知道该怎么做。

刚试过

看(玩家)

还是不行: enter image description here

【问题讨论】:

  • 来自the lookAt documentation :“旋转对象以面对世界空间中的一个点。”。只要给它玩家的协调

标签: javascript three.js


【解决方案1】:

如果僵尸和玩家都不是你应该能够使用的任何东西的父级

zombieMesh.lookAt(playerMesh.position);

请注意,lookAt 使模型的正 Z 轴指向目标。

'use strict';  // eslint-disable-line

/* global THREE, document, requestAnimationFrame  */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas: canvas});

  const fov = 60;
  const aspect = 2;  // the canvas default
  const zNear = 0.1;
  const zFar = 1000;
  const camera = new THREE.PerspectiveCamera(fov, aspect, zNear, zFar);
  camera.position.set(14, 8, 6);
  camera.lookAt(-2, -2, 0);

  const scene = new THREE.Scene();

  {
    const light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(0, 20, 0);
    scene.add(light);
  }

  {
    const light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(1, 2, 4);
    scene.add(light);
  }

  const groundGeometry = new THREE.PlaneBufferGeometry(50, 50);
  const groundMaterial = new THREE.MeshPhongMaterial({color: 0xCC8866});
  const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial);
  groundMesh.rotation.x = Math.PI * -.5;
  groundMesh.receiveShadow = true;
  scene.add(groundMesh);
  
  const zombieGeo = new THREE.ConeBufferGeometry(1, 1, 6);
  zombieGeo.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI * 0.5));
  const zombieMat = new THREE.MeshPhongMaterial({color: 'green', flatShading: true});
  const zombieMeshes = [];
  function makeZombie(x, z) {
    const zombieMesh = new THREE.Mesh(zombieGeo, zombieMat);
    scene.add(zombieMesh);
    zombieMesh.position.set(x, 1, z);
    zombieMeshes.push(zombieMesh);
  }
    
  for (let v = -5; v <= 5; v += 5) {
    makeZombie(v, -10);
    makeZombie(v,  10);
    makeZombie(-5, v);
    makeZombie( 5, v);
  }
  
  const playerGeo = new THREE.SphereBufferGeometry(1, 6, 4);
  const playerMat = new THREE.MeshPhongMaterial({color: 'red', flatShading: true});
  const playerMesh = new THREE.Mesh(playerGeo, playerMat);
  scene.add(playerMesh);
    
  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render(time) {
    time *= 0.001;

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }
    
    playerMesh.position.set(Math.sin(time) * 6, 1, Math.cos(time) * 6);

    for (const zombieMesh of zombieMeshes) {
      zombieMesh.lookAt(playerMesh.position);
    }

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<canvas id="c"></canvas>

【讨论】:

    【解决方案2】:

    它看起来像一个第一人称游戏,所以我认为你可以使用一个棘手的工作......

        function ZombieDirectionChanger(o){
                    console.log("Camera position has changed");
                    zombie.lookAt(camera.position);
                    console.log("Zombie has been rotated towards you");
                }
    
        controls.addEventListener('change', ZombieDirectionChanger);
    
    

    本质上,因为你的“眼睛”总是透过相机,所以无论你的“眼睛”在哪里,你都可以让僵尸跟着你。函数说改变僵尸位置,事件监听器正在监听相机变化。

    我没有看到任何示例代码,但请确保您的 lookAt 语句在对象范围内!我对发生在我身上的事情感到内疚......

    【讨论】:

      【解决方案3】:

      当您在 ThreeJS 中使用 lookAt 时,它足够聪明,可以自动从对象的位置进行计算,但是您的代码失败了,因为您尝试计算对象周围的方向,它应该在哪里看

      让你的代码更短:

      self.lookAt(player);
      

      【讨论】:

      • 文档说只有 lookAt 接受 3 个坐标或 Vector3。它可以从对象中提取坐标吗?
      • @Seblor 当您将 1 个参数传递给 lookAt 时,它会调用 Vector3d.copy 将其中的信息复制到临时对象,这只会查看对象是否具有键 x、@ 987654329@,z,您可以在问题中看到player 对象具有这三个属性,因此它是有效的(甚至可能问题中的player 对象已经是@987654333 @,但从操作所暴露的内容来看,它应该已经工作了)
      • 我不知道它会做一个复制,而 Vector3.copy 就是这样工作的。谢谢!
      • @Seblor 我在浏览源码时也了解到:Object3D.lookatVector3d.copy
      • 照你说的做了。不行,僵尸只是指向完全不同的方向
      猜你喜欢
      • 2017-09-23
      • 2013-11-06
      • 2013-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多