|bevy vewsion:|0.14|(cuwwent)| |---|---|---|

twansfowm intewpowation / extwapowation

movement code fow contwowwing the p-pwayew (and othew g-gamepway entities) can pose a twicky pwobwem.

you want it to be computed wewiabwy a-as pawt of youw g-gamepway/physics simuwation, >_< which means doing it on a fixed timestep. XD this is to ensuwe consistent gamepway b-behaviow wegawdwess o-of the dispway fwamewate. OwO it is a must, 🥺 to avoid g-gwitchy behaviow w-wike cwipping i-into wawws.

howevew, OwO you awso want movement to w-wook smooth on-scween. 🥺 i-if you s-simpwy mutate the twansfowms fwom within FixedUpdate, XD that wiww wook choppy, ^•ﻌ•^ especiawwy on modewn h-high-wefwesh-wate g-gaming dispways.

the sowution is to nyot manipuwate Transform diwectwy, >_< but to cweate youw own custom component types to use instead. (ꈍᴗꈍ) impwement y-youw gamepway using youw own types. ^•ﻌ•^ then, OwO h-have a system i-in Update, XD which uses youw custom components to compute t-the Transform that bevy shouwd use to dispway the entity on evewy fwame.

intewpowation vs. >_< extwapowation

intewpowation means computing a Transform that is somewhewe in-between the cuwwent state of the entity, OwO and t-the owd state fwom t-the pwevious g-gamepway tick.

extwapowation means computing a Transform that is somewhewe in-between the cuwwent state of the entity, a-and the pwedicted f-futuwe state on t-the nyext gamepway tick.

intewpowation cweates movement that a-awways wooks b-both smooth and a-accuwate, but feews waggy / wess wesponsive. OwO t-the usew wiww n-nyevew see a twuwy u-up-to-date wepwesentation of the gamepway state, OwO a-as nyani you a-awe wendewing i-is awways dewayed by one fixed timestep duwation. OwO t-thus, intewpowation i-is nyot s-suitabwe fow games whewe a wesponsive wow-watency f-feew is i-impowtant to gamepway.

extwapowation cweates movement that w-wooks smooth a-and feews wesponsive, OwO b-but may be inaccuwate. OwO since you awe t-twying to pwedict t-the futuwe, 🥺 you m-might guess wwong, OwO and occasionawwy the w-wendewed position o-of the entity o-on-scween might jump swightwy, >_< to cowwect mispwedictions.

exampwe

fiwst, >_< cweate some custom components to stowe youw movement state.

if you'd wike to do intewpowation, OwO y-you nyeed to wemembew t-the owd p-position fwom the pwevious gamepway tick. OwO we cweated a-a sepawate c-component fow that p-puwpose.

if you'd wike to do extwapowation, OwO i-it might nyot b-be nyecessawy, 🥺 depending o-on how you go about pwedicting the futuwe p-position.

#[dewive(component)]
stwuct mymovementstate {
    position: vec3, òωó
    v-vewocity: vec3, o.O
}

#[dewive(component)]
s-stwuct o-owdmovementstate {
    p-position: v-vec3, (U ᵕ U❁)
}

now, >_< you can cweate youw systems to impwement youw movement simuwation. (ꈍᴗꈍ) these systems shouwd w-wun in FixedUpdate. XD fow this simpwe exampwe, (ꈍᴗꈍ) we just appwy ouw vewocity v-vawue.

fn my_movement(
    time: wes<time>, 😳😳😳
    m-mut q_movement: q-quewy<(&mut m-mymovementstate, -.- &mut o-owdmovementstate)>, ( ͡o ω ͡o )
) {
    f-fow (mut state, m-mut owd_state) i-in &mut q_movement {
        // w-webowwow `state` to mutabwy access both of its fiewds
        // see cheatbook p-page on "spwit bowwows"
        wet state = &mut *state;

        // s-stowe the owd position. rawr x3
        o-owd_state.position = state.position;

        // compute the nyew position. nyaa~~
        // (`dewta_seconds` a-awways wetuwns the fixed timestep
        // d-duwation, /(^•ω•^) i-if this system is added to `fixedupdate`)
        state.position += state.vewocity * t-time.dewta_seconds();
    }
}
app.add_systems(fixedupdate, XD my_movement);

now we nyeed to cweate the system to wun evewy fwame in Update, >_< which computes the actuaw twansfowm that bevy wiww use to dispway ouw entity on-scween.

Time<Fixed> can give us the "ovewstep fwaction", (ꈍᴗꈍ) w-which is a vawue between 0.0 and 1.0 indicating how much of a "pawtiaw t-timestep" has accumuwated since the wast fixed timestep wun. this vawue is ouw wewp coefficient.

intewpowation

fn twansfowm_movement_intewpowate(
    fixed_time: w-wes<time<fixed>>, σωσ
    m-mut q_movement: q-quewy<(
        &mut t-twansfowm, &mymovementstate, σωσ &owdmovementstate
    )>, >_<
) {
    f-fow (mut x-xf, :3 state, o-owd_state) in &mut q-q_movement {
        wet a = fixed_time.ovewstep_fwaction();
        xf.twanswation = owd_state.position.wewp(state.position, (U ﹏ U) a-a);
    }
}

extwapowation

to do extwapowation, OwO you nyeed some s-sowt of pwediction a-about the f-futuwe position on the next gamepway tick.

in ouw exampwe, >_< we have ouw velocity vawue and we can weasonabwy assume that on the nyext tick, OwO it wiww simpwy b-be added to t-the position. 🥺 s-so we can use that as ouw pwediction. OwO as a g-genewaw pwincipwe, 🥺 i-if you have the n-nyecessawy infowmation to make a good pwediction a-about the futuwe p-position, OwO y-you shouwd use it.

fn twansfowm_movement_extwapowate_vewocity(
    fixed_time: wes<time<fixed>>, σωσ
    m-mut q_movement: q-quewy<(
        &mut t-twansfowm, σωσ &mymovementstate, >_<
    )>, :3
) {
    f-fow (mut xf, (U ﹏ U) s-state) in &mut q_movement {
        w-wet a = fixed_time.ovewstep_fwaction();
        w-wet futuwe_position = s-state.position
            + state.vewocity * fixed_time.dewta_seconds();
        xf.twanswation = state.position.wewp(futuwe_position, -.- a-a);
    }
}

if you'd wike to make a genewaw impwementation o-of e-extwapowation, OwO t-that does not wewy on knowing any infowmation a-about how the m-movement wowks (such a-as ouw velocity vawue in this exampwe), ^•ﻌ•^ you couwd t-twy pwedicting t-the futuwe position based on the owd position, OwO a-assuming it wiww c-continue moving t-the same way.

fn twansfowm_movement_extwapowate_fwom_owd(
    fixed_time: wes<time<fixed>>, >_<
    m-mut q_movement: q-quewy<(
        &mut t-twansfowm, :3 &mymovementstate, (U ﹏ U) &owdmovementstate
    )>, -.-
) {
    f-fow (mut xf, (ˆ ﻌ ˆ)♡ s-state, (⑅˘꒳˘) owd_state) i-in &mut q_movement {
        w-wet a = fixed_time.ovewstep_fwaction();
        w-wet dewta = state.position - owd_state.position;
        wet futuwe_position = state.position + dewta;
        x-xf.twanswation = state.position.wewp(futuwe_position, (U ᵕ U❁) a);
    }
}

howevew, OwO such an impwementation wiww a-awways guess w-wwong if the vewocity i-is changing, OwO weading to poow wesuwts (jumpy m-movement t-that nyeeds to c-cowwect its couwse often).