Hereβs an example, I made, of a randomized tap to place component.
If you want to use it, clone our World Effects studio project and replace the tap-place component with this code:
import * as ecs from '@8thwall/ecs'
const {THREE} = (window as any)
const {vec3} = ecs.math
const touchPoint = vec3.zero()
const assets = [
'assets/Soda_Can.glb',
'assets/Soda_Glass.glb',
'assets/Soda.glb',
]
ecs.registerComponent({
name: 'Tap Place',
schema: {
groundEntity: ecs.eid,
},
schemaDefaults: {
},
add: (world, component) => {
const {groundEntity} = component.schema
const {eid, schemaAttribute} = component
if (!groundEntity) {
console.error('Ground entity not set in schema')
return
}
const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()
let lastInteractionTime = 0
function handleInteraction(event) {
const newGroundEntity = schemaAttribute.get(eid).groundEntity
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(newGroundEntity)
if (!groundObject) {
console.error('Ground object not found for entity ID:', newGroundEntity)
return
}
const intersects = raycaster.intersectObject(groundObject, true)
if (intersects.length > 0) {
touchPoint.setFrom(intersects[0].point)
const newEid = world.createEntity()
const randomModel = `${assets[Math.floor(Math.random() * assets.length)]}`
console.log(randomModel)
ecs.GltfModel.set(world, newEid, {
url: randomModel,
})
world.setPosition(newEid, touchPoint.x, touchPoint.y, touchPoint.z)
ecs.Shadow.set(world, newEid, {
castShadow: true,
receiveShadow: true,
})
ecs.ScaleAnimation.set(world, newEid, {
fromX: 0,
fromY: 0,
fromZ: 0,
toX: 5,
toY: 5,
toZ: 5,
duration: 500,
loop: false,
easingFunction: 'elastic',
easeOut: true,
})
}
}
window.addEventListener('click', handleInteraction)
window.addEventListener('touchstart', handleInteraction)
},
})
Just keep in mind youβll need to change the assets at the top of the file to match your own assets.