Why is this interpolation not working?

I am making my own movement scripts (with more functions than Position Animation).
Somehow my code always returns Point B and I am pulling my hair why it does not interpolate properly.

All logs indicate no issues, except the log returning the position.
Any ideas?

// This is a component file. You can use this file to define a custom component for your project.
// This component will appear as a custom component in the editor.

import * as ecs from '@8thwall/ecs'  // This is how you access the ecs library.

ecs.registerComponent({
  name: 'LinearMovement',
  schema: {
    // Add data that can be configured on the component.
    movableObject: ecs.eid,
    pointA: ecs.eid,
    pointB: ecs.eid,
    duration: ecs.f32,
  },
  schemaDefaults: {
    duration: 20,

    // Add defaults for the schema fields.
  },
  data: {
    elapsedTime: ecs.f32,
    VPSFound: ecs.boolean,
    isRunning: ecs.boolean,
    // Add data that cannot be configured outside of the component.
  },
  add: (world, component) => {
    component.data.VPSFound = false
    component.data.elapsedTime = 0
    // Runs when the component is added to the world.
    // component.schema
    const {pointA, movableObject} = component.schema
    const posA = ecs.Position.get(world, pointA)
    ecs.Position.set(world, movableObject, {x: posA.x, y: posA.y, z: posA.z})
    // world.setPosition(movableObject, posA.x, posA.y, posA.z)

    const {eid, dataAttribute} = component
    // This runs when we find a VPS location
    const locationFound = () => {
      // This is safe because we're re-aquiring a cursor at the time we need it,
      // instead of using a stale cursor from before.
      const data = dataAttribute.cursor(eid)
      data.elapsedTime = 0
      data.VPSFound = true
      data.isRunning = true

      console.log('VPS Location Found')
    }
    world.events.addListener(world.events.globalId, 'reality.locationfound', locationFound)
  },
  tick: (world, component) => {
    if (component.data.VPSFound === false || component.data.isRunning === false) {
      return
    }

    function easeInOut(t) {
      return t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2 ** 2) / 2
    }
    // Runs every frame.
    const {duration, pointA, pointB, movableObject} = component.schema
    // Retrieve position of pointA and pointB
    const posA = ecs.Position.get(world, pointA)
    // Set properly
    console.log(posA)
    const posB = ecs.Position.get(world, pointB)
    // Set properly
    console.log(posB)
    // Calculate interpolation factor (0 to 1)
    const t = Math.min(component.data.elapsedTime / duration, 1)
    // Goes between 0 and 1 smoothly
    console.log(t)
    // Interpolate each coordinate
    const newX = posA.x + (posB.x - posA.x) * t
    const newY = posA.y + (posB.y - posA.y) * t
    const newZ = posA.z + (posB.z - posA.z) * t
    // Always returns PosB!!!
    console.log({x: newX, y: newY, z: newZ})

    // Set the new position for movableObject
    ecs.Position.set(world, movableObject, {x: newX, y: newY, z: newZ})
    // world.setPosition(movableObject, newX, newY, newZ)

    component.data.elapsedTime += world.time.delta

    if (component.data.elapsedTime > component.schema.duration) {
      console.log('Stopped moving')
      component.data.isRunning = false
    }
  },
  remove: (world, component) => {
    // Runs when the component is removed from the world.
  },
})

You should probably be using dataAttribute to access data on the component.

You could also use PositionAnimation instead of a custom component.

Do I also need to use DataAttributes in tick, even if it’s not in a nested method?

I know PositionAnimation is a thing as well, but I wanted to learn to use JS before using a ton of premade methods. This would allow me to properly understand what is happening and also make custom checks to pause it, etc. Having an object move via script sounded like a good start to use the engine.
And I wanted to wait for VPS to be found. I am not sure if child objects of the VPS location only start running when VPS is found.

For some reason PositionAnimation also teleports to the end with
ecs.PositionAnimation.set(world, movableObject, {autoFrom: true, toX: data.x, toY: data.y, toZ: data.z, duration: 40000, easeOut: true})

Hey Dylan,

Components won’t wait until the VPS location is found, you’ll need to setup your code to only run after the VPS event has fired.

Are you setting it in Tick?

It set it in Add, after the VPS Found event is fired (logged this to be correct)

Can you show a screenshot of the component attached to the entity and its properties?