【问题标题】:Accessing children of children in ThreeJS在 ThreeJS 中访问孩子的孩子
【发布时间】:2022-01-21 00:11:24
【问题描述】:

我一直在学习 ThreeJs,我是不是在尝试调用我的文件时卡住了。

让我先解释一下我想做什么! 我有 3 个模型要在页面上显示,因为人们滚动应该显示不同的表情符号,比如小部分,经典的 webapge 方式。

我从 blender 将这些模型导入到一个 gltb 文件中以提高性能,并且理论上可以节省时间,其中两个对象是组,另一个是网格。导入中没有其他内容。

但是,在使用 gltf loader 加载我的模型后,我无法找到一种方法来访问它们以将它们容纳在我希望它们所处的位置和旋转中。请帮忙。

我加载了我的场景:

gltfLoader.load(
'EMOJIS.gltf',
(gltf) =>
{
    gltf.scene.scale.set(0.25, 0.25, 0.25)
    gltf.scene.position.set(0, 0, 0)

    mixer = new THREE.AnimationMixer(gltf.scene)
    scene.add(gltf.scene)
}

之后我检查了我的日志以找到对象

console.log(scene)
console.log(scene.children)
console.log(scene.children[3])

第一个和第二个日志显示如下:

我意识到我应该联系场景孩子的孩子来获取我的 3 个表情符号:心、桃、心眼。 例如,我想我可以调用 scene.children[3].children[0] 。并调用心脏对象表情符号 但我不能打电话给他们?我尝试了很多方法,但它总是显示为未定义。

console.log(scene.children) 显示了一个从 0 到 3 的数组,在 [3] 插槽中我可以看到我想要的表情符号元素,但调用 console.log(scene.children[3]) 显示未定义,如何访问我想要的组?

打电话

var heart = scene.getObjectByName( "heart", true );

或通过他们的 ID(16、15 和 23)调用也显示未定义。

非常感谢所有帮助。

编辑:

在我的 consolde 调试上加上时间戳后,我意识到它在为表情符号调用我的对象引用后调用了 gltf 加载器,但我不确定为什么会发生这种情况或如何以正确的顺序设置它们? gltf 加载器位于脚本的顶部,随后调用下面的各个行,它不应该正确运行吗?是因为模型加载所需的时间吗?我该如何解决?

代码:

    gltfLoader.load(
    'EMOJIS.gltf',
    (gltf) => {
        gltf.scene.scale.set(0.5, 0.5, 0.5)
        gltf.scene.position.set(0, 0, 0)
        scene.add(gltf.scene)

        // Animation
        mixer = new THREE.AnimationMixer(gltf.scene)

        gui.add(gltf.scene.position, 'y').min(-3).max(3).step(0.01).name('position y')
        gui.add(gltf.scene.position, 'x').min(-3).max(3).step(0.01).name('position x')
        gui.add(gltf.scene.position, 'z').min(-3).max(3).step(0.01).name('position z')

        //gltf.scene.children[2].material.roughness = 1

        gltf.scene.children[0].position.x = 2
        gltf.scene.children[1].position.x = - 2
        gltf.scene.children[2].position.x = 2

        gltf.scene.children[0].position.y = - objectsDistance * 0
        gltf.scene.children[1].y = - objectsDistance * 1
        gltf.scene.children[2].y = - objectsDistance * 2

        console.log("Emoji Inside Loader, Line 99")
        console.log(gltf.scene.children[0])

        /*
        var heart = gltf.scene.getObjectByName("heart", true);
        var heartEyes = gltf.scene.getObjectByName("heartEyes", true);
        var peach = gltf.scene.getObjectByName("peach", true); */

        // loop through all children and create a property 
        // for every child based on it's name
        gltf.scene.children.forEach((item) => {
            emoji[item.name] = item;
        })
        // then you can access every child through 
        // the named property of the shirt object

        console.log("emoji array")
        console.log(emoji.peach)
        console.log(emoji.heart)
        console.log(emoji.heart.rotation)
        console.log(emoji.heartEyes)
        loaded = true;


      }
    )


    console.log("Main scene")
    console.log(scene)
    console.log(scene.children)
    console.log(scene.children[6])


    console.log("Emoji outside of the loader, line 133?")
    console.log(emoji)
    console.log(emoji[heart])
    console.log(emoji[0])
    console.log(emoji.name[heart])
    console.log("--- --- ---")

调试:

【问题讨论】:

    标签: javascript three.js gltf


    【解决方案1】:

    我在访问衬衫模型的子代时遇到了一些麻烦,因此我创建了一个对象,其中包含子代的名称(在 Blender 中命名)作为属性,以便于访问。也许这会对你有所帮助:

         // prepare shirt (js) object
         let shirt = {};
    
            ... after importing the gltf ...
    
          scene.add(gltf.scene);
    
          // loop through all children and create a property 
          // for every child based on it's name
          gltf.scene.children.forEach((item) => {
            shirt[item.name] = item;
          });
    
          // then you can access every child through 
          // the named property of the shirt object
    
          shirt.Back.children[0].material = shirtMat;
    
          shirt.Sleeves.children[0].material = shirtMat;
    
          shirt.Front.children[0].material = shirtMat;
          shirt.Front.children[1].material = buttonMat;
    
          shirt.CollarClassic.children[0].material = shirtMat;
    
          shirt.CollarCut.children[0].material = shirtMat;
          shirt.CollarCut.visible = false;
    
          shirt.CollarButton.children[0].material = shirtMat;
          shirt.CollarButton.children[1].material = buttonMat;
          shirt.CollarButton.visible = false;
    
            ... etc
    

    【讨论】:

    • 您好!我意识到这种方法对我也不起作用,我终于想在我的调试控制台中添加时间戳并意识到我的问题一直是“表情符号”的每次调用都在以某种方式初始化加载程序之前完成,即使我虽然他们的顺序是正确的。但无论如何,这种见解似乎很重要,谢谢。我会继续寻找它为什么不能正常工作。
    • 我已经发现了问题所在,这种识别网格的方法被证明对找出问题最有帮助 10/10
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 2016-08-21
    • 2014-10-16
    相关资源
    最近更新 更多