Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 仅检测第一次碰撞(使用光线投射进行碰撞检测)_Javascript_Three.js - Fatal编程技术网

Javascript 仅检测第一次碰撞(使用光线投射进行碰撞检测)

Javascript 仅检测第一次碰撞(使用光线投射进行碰撞检测),javascript,three.js,Javascript,Three.js,我正在构建一个无休止的跑步者风格的游戏,其中(0,0)处的角色只能在X轴上左右移动(使用箭头键或鼠标)。有两种类型的对象从z=-10000向角色移动,一旦它们到达z=10000(即在角色后面和屏幕外),它们将重置为z=-10000我正在使用以下光线投射代码检测角色和两种类型对象之间的碰撞 本质上,光线是在渲染循环的每一帧中从每个角色顶点发射的。如果光线与一个对象顶点相交,且距离接近角色(不确定其使用的确切距离),则会检测到碰撞 let cooldown = false; let objectMe

我正在构建一个无休止的跑步者风格的游戏,其中(0,0)处的角色只能在X轴上左右移动(使用箭头键或鼠标)。有两种类型的对象从
z=-10000
向角色移动,一旦它们到达
z=10000
(即在角色后面和屏幕外),它们将重置为
z=-10000
我正在使用以下光线投射代码检测角色和两种类型对象之间的碰撞

本质上,光线是在渲染循环的每一帧中从每个角色顶点发射的。如果光线与一个对象顶点相交,且距离接近角色(不确定其使用的确切距离),则会检测到碰撞

let cooldown = false;
let objectMesh;
let collisionResults;
let timeout;

function detectCollisionRaycaster(originObject, collidedObjects) {
    if (this.isCollision(originObject, collidedObject)) {
        cooldown = true;
        if (timeout) {
           clearTimeout(timeout);
        }
        timeout = setTimeout(function () {
            cooldown = false;
        }, 500);
    }
}

function isCollision(originObject, collidedObjects) {
    let originPoint = originObject.position.clone();

    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() );
        collisionResults = raycaster.intersectObjects( collidedObjects, true );
        if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() && !cooldown) {
            console.info("Object Collided");
            return true;
        }
    }

    return false;
}
这是我的代码:

这将在渲染循环中运行:

detectCollisionRaycaster(character, objectsArray);
这是碰撞检测功能:

let cooldown = false;
let objectMesh;
let collisionResults;

function detectCollisionRaycaster(originObject, collidedObjects) {

let originPoint = originObject.position.clone();

    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() );
        collisionResults = raycaster.intersectObjects( collidedObjects, true );
        if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() && !cooldown) {

            cooldown = true;

            console.info("Object Collided");

            setTimeout(function(){
                collisionResults.length = 0;
                cooldown = false;
            }, 500);

        }
    }
}
让冷却时间=假;
让物体啮合;
让冲突产生结果;
功能检测碰撞光线投射器(原始对象、碰撞对象){
让originPoint=originObject.position.clone();
对于(变量vertexIndex=0;vertexIndex0&&collisionResults[0]。距离
问题

碰撞代码已触发多次。我非常确定这是因为对象正朝角色移动,因此对象的顶点与光线碰撞超过一帧,因此只要对象在敌人的“内部”,碰撞代码就会运行

我想要什么:

我希望碰撞检测代码显式触发一次,暂停碰撞检测一段时间,直到对象不再与角色碰撞,然后继续检测碰撞

我尝试过的


我尝试在碰撞检测代码中设置一个超时函数,我认为该函数将停止在渲染循环中运行碰撞检测,直到该时间结束,但它似乎只需要运行一次代码,暂停超时,然后在对象运行的所有时间继续运行碰撞检测代码字符的“内部”。

由于在发现冲突时没有终止循环,因此即使满足
条件,它也会继续执行剩余的迭代

类似这样的方法可以帮助您更好地组织逻辑,因为它可以分离出您对以前的冲突检测方法所承担的一些责任。通过两种方法,我们将您的逻辑分离为一种,它只告诉我们是否发生了冲突(
isCollision
),以及另一种方法,该方法使用
isCollision
在检测到碰撞时适当设置
冷却时间

let cooldown = false;
let objectMesh;
let collisionResults;
let timeout;

function detectCollisionRaycaster(originObject, collidedObjects) {
    if (this.isCollision(originObject, collidedObject)) {
        cooldown = true;
        if (timeout) {
           clearTimeout(timeout);
        }
        timeout = setTimeout(function () {
            cooldown = false;
        }, 500);
    }
}

function isCollision(originObject, collidedObjects) {
    let originPoint = originObject.position.clone();

    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() );
        collisionResults = raycaster.intersectObjects( collidedObjects, true );
        if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() && !cooldown) {
            console.info("Object Collided");
            return true;
        }
    }

    return false;
}
让冷却时间=假;
让物体啮合;
让冲突产生结果;
让超时;
功能检测碰撞光线投射器(原始对象、碰撞对象){
if(此.isCollision(原始对象、碰撞对象)){
冷却时间=真;
如果(超时){
clearTimeout(超时);
}
超时=设置超时(函数(){
冷却时间=假;
}, 500);
}
}
函数isCollision(原始对象、碰撞对象){
让originPoint=originObject.position.clone();
对于(变量vertexIndex=0;vertexIndex0&&collisionResults[0]。距离

编辑:这将保持冷却,直到没有对象与玩家发生碰撞。如果你想设置它,以便暂停直到触发碰撞的特定对象是被检查的对象,那么你需要保留对该对象的引用并检查它,而不是针对全套玩家tices+对象。一种方法是从
isCollision
方法返回对碰撞对象的引用,而不是布尔值,然后使用另一种方法从该对象显式地光线投射到播放器顶点,以确定碰撞何时结束。

非常感谢,这解决了我的问题,并且完全正确我在问题中问了什么!:)如果我试图删除碰撞检测代码中的碰撞对象(在
return true
之前的一行),它会中断并返回多次运行碰撞检测代码…知道为什么吗?我正在使用此代码删除对象:
scene.remove(scene.getObjectByName(collisionResults[0].object.parent.name));
我觉得这是因为