Sounds like a JavaScript floating error, not an 8thwall error. Add:
if (isFinite([your value])) {
// your code
}
tbh not sure where to add this, since All I doing is extending on tap to place example, instead of just placing model, I am also attaching positional audio to it, so I am not explicitly setting any value apart from setting volume of audio which is hardcoded while cloning.
import * as ecs from '@8thwall/ecs'
const {THREE} = (window as any)
// Components used by the Tap Place spawner
const {BoxGeometry, Material, Position, Quaternion, Scale, Shadow, ScaleAnimation} = ecs
const {vec3} = ecs.math
const componentsForClone = [
Position, Quaternion, Scale, Shadow, BoxGeometry, Material, ScaleAnimation, ecs.PositionAnimation,
ecs.RotateAnimation, ecs.CustomPropertyAnimation, ecs.CustomVec3Animation, ecs.FollowAnimation,
ecs.LookAtAnimation, ecs.GltfModel, ecs.Collider, ecs.ParticleEmitter, ecs.Ui, ecs.Audio,
]
const cloneComponents = (sourceEid, targetEid, world) => {
componentsForClone.forEach((component, i) => {
if (component.has(world, sourceEid)) {
const properties = component.get(world, sourceEid)
const newProps = {}
Object.keys(properties).forEach((key) => {
const value = properties[key]
if (typeof value === 'number') {
if (Number.isFinite(value)) {
newProps[key] = value
} else {
console.error(key, ' : Value is not finite')
}
} else {
newProps[key] = value
}
})
if (i === 17) {
component.set(world, targetEid, {...newProps, volume: 0.8, paused: false, maxDistance: 100})
} else {
component.set(world, targetEid, {...newProps})
}
// console.log(newProps)
}
})
}
const v = vec3.zero()
const touchPoint = vec3.zero()
let objectCounter = 0
ecs.registerComponent({
name: 'Tap Place',
schema: {
entityToSpawn1: ecs.eid,
entityToSpawn2: ecs.eid,
entityToSpawn3: ecs.eid,
audioEntity1: ecs.eid,
audioEntity2: ecs.eid,
audioEntity3: ecs.eid,
groundEntity: ecs.eid,
},
add: (world, component) => {
// const overlay = document.createElement('div')
// overlay.style.position = 'absolute'
// overlay.style.top = '0px'
// overlay.style.bottom = '0px'
// overlay.style.left = '0px'
// overlay.style.right = '0px'
// overlay.style.background = 'black'
// overlay.style.display = 'flex'
// overlay.style.justifyContent = 'center'
// overlay.style.alignItems = 'center'
// const button = document.createElement('button')
// button.innerText = 'Start'
// overlay.appendChild(button)
// // console.log(world)
// document.body.appendChild(overlay)
const {groundEntity, entityToSpawn1, entityToSpawn2, entityToSpawn3, audioEntity1, audioEntity2, audioEntity3} = component.schema
if (!groundEntity) {
console.error('Ground entity not set in schema')
return
}
const pianoObject = world.three.entityToObject.get(entityToSpawn1)
pianoObject.visible = false
const saxophoneObject = world.three.entityToObject.get(entityToSpawn2)
saxophoneObject.visible = false
const violinObject = world.three.entityToObject.get(entityToSpawn3)
violinObject.visible = false
const entityOptions = [entityToSpawn1, entityToSpawn2, entityToSpawn3]
const entityAudioOptions = [audioEntity1, audioEntity2, audioEntity3]
// const audioOptions = ['https://raw.githubusercontent.com/Bhushan-Ctruh/assets/main/piano.mp3', 'https://raw.githubusercontent.com/Bhushan-Ctruh/assets/main/violin.mp3', 'https://raw.githubusercontent.com/Bhushan-Ctruh/assets/main/saxophone.mp3']
const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()
let lastInteractionTime = 0
function handleInteraction(event) {
if (objectCounter === 3) return
const currentTime = Date.now()
if (currentTime - lastInteractionTime < 500) {
return
}
lastInteractionTime = currentTime
if (event.touches) {
mouse.x = (event.touches[0].clientX / window.innerWidth) * 2 - 1
mouse.y = -(event.touches[0].clientY / window.innerHeight) * 2 + 1
} else {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
}
raycaster.setFromCamera(mouse, world.three.activeCamera)
const groundObject = world.three.entityToObject.get(groundEntity)
if (!groundObject) {
console.error('Ground object not found for entity ID:', groundEntity)
return
}
const intersects = raycaster.intersectObject(groundObject, true)
if (intersects.length > 0) {
touchPoint.setFrom(intersects[0].point)
const prompt = document.getElementById('promptText')
if (prompt) {
prompt.style.display = 'none'
}
const newEid = world.createEntity()
const selectedEntityToSpawn = entityOptions[objectCounter]
const selectedAudio = entityAudioOptions[objectCounter]
if (selectedEntityToSpawn) {
// Clone an entity at the target position, with an initial scale of zero.
cloneComponents(selectedEntityToSpawn, newEid, world)
cloneComponents(selectedAudio, newEid, world)
Position.set(world, newEid, touchPoint)
Scale.set(world, newEid, v.makeZero())
} else {
alert('Somthing went wrong')
}
console.log(objectCounter)
ScaleAnimation.set(world, newEid, {
fromX: 0,
fromY: 0,
fromZ: 0,
toX: objectCounter === 1 ? 0.1 : 1,
toY: objectCounter === 1 ? 0.1 : 1,
toZ: objectCounter === 1 ? 0.1 : 1,
duration: 500,
loop: false,
easeIn: true,
easeOut: true,
})
objectCounter++
}
}
// button.addEventListener('click', (e) => {
// e.stopPropagation()
// overlay.remove()
// })
window.addEventListener('pointerup', handleInteraction)
},
})
Though as you suggested I have added finite check for number values, but it still seems to break. Also one thing I have observed that it breaks a lot on ios devices compared to android.
const value === ‘number’ seems to be the issue there. If “value” can be Infinity, typeof value === ‘number’ still results in try for infinite numbers. I would change that to:
if (typeof value === ‘number’ && isFinite(value))
You can’t simply replace the typeof since arrays can also be finite and you want to be sure to associate it correctly.
Or, better yet, refactor to a switch case so you’re not dealing with nested if statements:
Object.keys(properties).forEach((key) => {
const value = properties[key]
switch(typeof value){
case 'number':
if (Number.isFinite(value)) newProps[key] = value
break;
default:
newProps[key] = value
}
})
replaced with switch statement and it still breaks with same issue. I tried logging and I don’t think thats where the issue is tbh.
Found this thread on three js Failed to execute 'linearRampToValueAtTime' on 'AudioParam' · Issue #20718 · mrdoob/three.js · GitHub
Yea… Honestly have no idea then. Sorry… (Canadian)
But then is it issue with my implementation or is it some issue with 8th wall. How should I even proceed?