首页 > 解决方案 > Three.js - 通过来自组的光线投射检测碰撞

问题描述

我正在创建一个无尽的跑步游戏,其中滑板上的角色在 (0,0,0) 处是静止的,并且风景向该点移动,并在屏幕外重置为“后退”。

游戏的目的是躲避向你驶来的汽车,并收集比汽车向角色移动的速度慢的物体,两者都可以获得积分。我THREE.Raycaster用来检测滑板和我工作得很好的汽车/物体之间的碰撞(汽车和物体的不同碰撞场景)。

问题

我正在检测滑板和物体之间的碰撞,因为滑板在-z方向(物体来自哪里)上比角色延伸得更远,所以它首先“撞击”一个物体。滑板是一组对象(仍然是 aTHREE.Object3D而不是 a THREE.Group(),但它们的功能相同),例如包含 4 个轮子、两辆卡车等……所以我不能使用主要SkateBoardGroup对象来检测碰撞,因为它不是 aMesh和没有顶点,顶点决定了光线从哪里投射。

最接近Mesh对象的是SkateBoardBaseRight Mesh,它是 SkateBoardBase 对象(包含 3 个网格)的子对象,它本身是主对象的子SkateBoardGroup对象。我目前正在使用Mesh以下代码访问它并从中进行光线投射Mesh

objectMesh = SkateBoardGroup.children[0].children[2];

我希望能够从顶层进行光线投射,SkateBoardGroup因为滑板有时会旋转,因此SkateBoardBaseRight网格并不最靠近物体。

我想要的是

我将不胜感激解释和/或代码示例,说明我如何从 raycast 中进行光线投射,THREE.Object3D SkateBoardGroup而不必深入到对象的子项中。

将 设置raycaster.intersetObjects为递归并不是我要寻找的,因为那是滑板碰撞的对象。

这是我的光线投射代码:

我两次调用此函数,一次用于汽车,一次用于其他对象

originObjectSkateBoardGroup,collidedObjects是包含汽车或其他对象的数组,并且doesCollidedObjectsEndGame是一个布尔标志,用于决定它是哪种类型的对象(汽车或其他对象)

let cooldown = false; // cooldown reset when try-again clicked
let cooldown2 = false;

function detectCollisionRaycaster(originObject, collidedObjects, 
doesCollidedObjectsEndGame) {

let objectMesh = originObject.children[0].children[2];

let originPoint = originObject.position.clone();

if (cooldown === false) {
    for (var vertexIndex = 0; vertexIndex < objectMesh.geometry.vertices.length; vertexIndex++) {
        var localVertex = objectMesh.geometry.vertices[vertexIndex].clone();
        var globalVertex = localVertex.applyMatrix4( objectMesh.matrix );
        var directionVector = globalVertex.sub( objectMesh.position );

        var raycaster = new THREE.Raycaster( originPoint, directionVector.clone().normalize() );
        var collisionResults = raycaster.intersectObjects( collidedObjects, true );
        if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) {
            if (doesCollidedObjectsEndGame) {
                // car objects collided
                gameIsOver = true;
                cooldown = true;
            } else {
                if (cooldown2 === false) {
                    cooldown2 = true;
                    // other objects collided
                    setTimeout(function(){
                        cooldown2 = false;
                    }, 100);
                }
            }
        }
    }
}
}

标签: javascriptthree.js

解决方案


推荐阅读