Three.js - 使用scene.getObjectByName()

时间:2018-04-20 09:21:35

标签: javascript three.js

对于我的游戏,我正在加载4个不同的对象(建筑物),并在for循环中将每个对象克隆15次。我将每个克隆添加到masterBuildingArray数组中,然后使用forEach循环遍历该数组。每个建筑物都使用.MTL.OBJ装载机加载。

建筑物是针对一个城市的,因此我首先使用算法随机化阵列中建筑物的顺序,然后使用if语句设置每10个建筑物的位置,以便它们排成一行在中央道路两侧分三排。

我的问题

我希望能够从这个数组中删除任何对象,因为我有一些需要替换阵列中特定建筑物的特殊(地标)建筑物(基本上它们需要处于某些位置)。我知道,例如,右侧最靠近摄像机的建筑物(即中央道路右侧3x10建筑物网格的左下方)的位置大致为(550, -75, 800)XZ位置略有随机化,因此"大致"。

我的代码位于问题的底部

我的想法

我在我的forEach循环中添加了一个索引计数器,然后我还将其分配给每个建筑物userData,以便我可以访问每个建筑物。我的想法是在if循环中添加forEach语句,如下所示:

if (highriseBuilding.userData.index == 31) {
    initialBuildingName = highriseBuilding.name;
    highriseBuilding.name = highriseBuilding.name + "_toBeRemoved";
}

我会将字符串"_toBeRemoved"添加到我想要删除的位置的建筑物名称中,然后以某种方式删除该对象。

我想我可以简单地删除它:

scene.remove(scene.getObjectByName(initialBuildingName + "_toBeRemoved"));

然而,无论我在哪里放置它(在最初的forEach循环内部,在它自己的forEach循环之后无法正常工作,该循环在masterBuildingArray之后运行第一次循环等...)

这是我的代码:

如何加载建筑物的示例:

function createHighrise4() {

var onProgress = function ( xhr ) {
    if ( xhr.lengthComputable ) {
        var percentComplete = xhr.loaded / xhr.total * 100;
        console.log( Math.round(percentComplete, 2) + '% downloaded' );
    }
};

var onError = function ( xhr ) { };
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader(loadingManager) );
var mtlLoader = new THREE.MTLLoader(loadingManager);
mtlLoader.setPath( '/objects/highrise4_white_curved/' );

mtlLoader.load( 'highrise4_white_curved.mtl', function( materials ) {

    materials.preload();

    var objLoader = new THREE.OBJLoader(loadingManager);

    objLoader.setMaterials( materials );
    objLoader.setPath( '/objects/highrise4_white_curved/' );

    objLoader.load( 'highrise4_white_curved.obj', function ( highrise4_white_curved ) {

        highrise4_white_curved.scale.set(10,10,10);

        highrise4_white_curved.traverse( function ( child ) {
                if ( child instanceof THREE.Mesh ) {
                    child.receiveShadow = true;
                    child.castShadow = true;
                }
            } );

        for (let i = 0; i < 15; i++) {

            clonedHighrise4 = highrise4_white_curved.clone();
            clonedHighrise4.name = "highrise4_white_curved";
            masterBuildingArray.push(clonedHighrise4);

        }

    }, onProgress, onError );

});

}

每个建筑物的放置方式+我尝试的解决方案:

function loopThroughBuildingArray() {

randomShuffle(masterBuildingArray);

masterBuildingArray.forEach(function(highriseBuilding, i){

    let building_randomYScale = Math.floor(Math.random() * (15 - 10) + 10);
    highriseBuilding.userData.index = i;

    if (i < 10) {
        rowLeft1.push(highriseBuilding);
        highriseBuilding.position.z = Math.floor(Math.random() * (950 - 850) + 850);
        highriseBuilding.position.x = incrementLeft1;
        incrementLeft1 -= Math.floor(Math.random() * (800 - 550) + 550);
    }
    if (i >= 10 && i < 20) {
        rowLeft2.push(highriseBuilding);
        highriseBuilding.position.z = Math.floor(Math.random() * (50 - -50) + -50);
        highriseBuilding.position.x = incrementLeft2;
        incrementLeft2 -= Math.floor(Math.random() * (800 - 550) + 550);
    }
    if (i >= 20 && i < 30) {
        rowLeft3.push(highriseBuilding);
        highriseBuilding.position.z = Math.floor(Math.random() * (-950 - -850) + -850);
        highriseBuilding.position.x = incrementLeft3;
        incrementLeft3 -= Math.floor(Math.random() * (800 - 550) + 550);
    }
    if (i >= 30 && i < 40) {
        rowRight1.push(highriseBuilding);
        highriseBuilding.position.z = Math.floor(Math.random() * (950 - 850) + 850);
        highriseBuilding.position.x = incrementRight1;
        incrementRight1 += Math.floor(Math.random() * (800 - 550) + 550);
    }
    if (i >= 40 && i < 50) {
        rowRight2.push(highriseBuilding);
        highriseBuilding.position.z = Math.floor(Math.random() * (50 - -50) + -50);
        highriseBuilding.position.x = incrementRight2;
        incrementRight2 += Math.floor(Math.random() * (800 - 550) + 550);
    }
    if (i >= 50 && i < 60) {
        rowRight3.push(highriseBuilding);
        highriseBuilding.position.z = Math.floor(Math.random() * (-950 - -850) + -850);
        highriseBuilding.position.x = incrementRight3;
        incrementRight3 += Math.floor(Math.random() * (800 - 550) + 550);
    }
    // 31 is building in position: right side, bottom left corner (closest to camera & road on right side)

    if (highriseBuilding.userData.index == 31) {
        initialBuildingName = highriseBuilding.name;
        highriseBuilding.name = highriseBuilding.name + "_toBeRemoved";

    }

    highriseBuilding.scale.y = building_randomYScale;
    highriseBuilding.position.y = -75;
//        highriseBuilding.position.y = (highriseBuildingBoundingBox.max.y * highriseBuilding.scale.y) / 2;


    cityScape.add(highriseBuilding);

});

cityScape.position.z = -9300;
cityScape.scale.set(0.5, 0.5, 0.5);
scene.add(cityScape);
scene.remove(scene.getObjectByName(initialBuildingName + "_toBeRemoved"));
}

我真的很感激任何帮助,因为我完全坚持如何做一些我认为简单的事情!

1 个答案:

答案 0 :(得分:0)

任何三个对象的默认名称都是空字符串。 scene.getObjectByName返回具有给定名称的第一个对象。因此scene.remove(scene.getObjectByName(initialBuildingName + "_toBeRemoved"));将始终返回第一个对象,因为您添加到场景中的所有建筑物都将具有相同的名称&#34; _toBeRemoved &#34;。尝试为每个建筑物提供唯一的名称。

希望这有帮助。