{"id":15137876,"url":"https://github.com/jondolf/bevy_transform_interpolation","last_synced_at":"2025-10-23T13:30:52.291Z","repository":{"id":252810811,"uuid":"841447816","full_name":"Jondolf/bevy_transform_interpolation","owner":"Jondolf","description":"Transfom interpolation for fixed timesteps for the Bevy game engine.","archived":false,"fork":false,"pushed_at":"2024-12-05T22:44:23.000Z","size":148,"stargazers_count":43,"open_issues_count":2,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-01T12:53:57.481Z","etag":null,"topics":["bevy","easing","gamedev","interpolation","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Jondolf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["Jondolf"]}},"created_at":"2024-08-12T12:31:39.000Z","updated_at":"2025-01-23T19:19:14.000Z","dependencies_parsed_at":"2024-08-12T18:15:03.248Z","dependency_job_id":"eddf289d-7ae8-4a40-9ad4-d62711122c35","html_url":"https://github.com/Jondolf/bevy_transform_interpolation","commit_stats":{"total_commits":11,"total_committers":1,"mean_commits":11.0,"dds":0.0,"last_synced_commit":"93b7036f754aa86ec03fb1b728677163c82fbf88"},"previous_names":["jondolf/bevy_transform_interpolation"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jondolf%2Fbevy_transform_interpolation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jondolf%2Fbevy_transform_interpolation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jondolf%2Fbevy_transform_interpolation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jondolf%2Fbevy_transform_interpolation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jondolf","download_url":"https://codeload.github.com/Jondolf/bevy_transform_interpolation/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237834629,"owners_count":19373759,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bevy","easing","gamedev","interpolation","rust"],"created_at":"2024-09-26T07:03:04.342Z","updated_at":"2025-10-23T13:30:52.284Z","avatar_url":"https://github.com/Jondolf.png","language":"Rust","readme":"# `bevy_transform_interpolation`\n\n[![MIT/Apache 2.0](https://img.shields.io/badge/license-MIT%2FApache-blue.svg)](https://github.com/Jondolf/bevy_transform_interpolation#license)\n[![ci](https://github.com/Jondolf/bevy_transform_interpolation/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Jondolf/bevy_transform_interpolation/actions/workflows/ci.yml)\n[![crates.io](https://img.shields.io/crates/v/bevy_transform_interpolation?label=crates.io)](https://crates.io/crates/bevy_transform_interpolation)\n[![docs.rs](https://img.shields.io/docsrs/bevy_transform_interpolation?label=docs.rs)](https://docs.rs/bevy_transform_interpolation)\n\nA drop-in `Transform` interpolation solution for fixed timesteps for the [Bevy game engine](https://bevyengine.org).\n\n## What Is This For?\n\nA lot of gameplay logic and movement systems typically use a fixed timestep to produce consistent and stable behavior\nregardless of the frame rate. Notable examples include physics simulation and character movement.\n\nHowever, this can make movement appear choppy, especially on displays with a high refresh rate.\nTo achieve visually smooth movement while using a fixed timestep, the visual transform must be smoothed\nindependently of the \"true\" gameplay transform.\n\nThe most common way to do this is to use **transform interpolation**, which interpolates movement from the previous\nstate to the current state. This could be done by storing the current and old gameplay positions in their own components\nand interpolating `Transform` using them:\n\n```rust\nuse bevy::prelude::*;\n\n#[derive(Component, Deref, DerefMut)]\nstruct Position(Vec3);\n\n#[derive(Component, Deref, DerefMut)]\nstruct OldPosition(Vec3);\n\nfn interpolate_transforms(\n    mut query: Query\u003c(\u0026mut Transform, \u0026Position, \u0026OldPosition)\u003e,\n    fixed_time: Res\u003cTime\u003cFixed\u003e\u003e\n) {\n    // How much of a \"partial timestep\" has accumulated since the last fixed timestep run.\n    // Between `0.0` and `1.0`.\n    let overstep = fixed_time.overstep_fraction();\n\n    for (mut transform, position, old_position) in \u0026mut query {\n        // Linearly interpolate the translation from the old position to the current one.\n        transform.translation = old_position.lerp(position.0, overstep);\n    }\n}\n```\n\nIn fact, you could simply plug the above implementation into your own application if you wanted to!\n\nHowever, it requires you to use `Position` for gameplay logic, and to manage `OldPosition` somewhere.\nThis can be annoying, and is incompatible with third party libraries that expect to be able to modify\nthe transform directly.\n\n`bevy_transform_interpolation` aims to be a drop-in solution that allows easy and efficient transform interpolation,\nwhile still allowing the usage of `Transform` for gameplay logic. It should be automatically compatible with physics engines\nsuch as [Avian](https://github.com/Jondolf/avian) and [`bevy_rapier`](https://github.com/dimforge/bevy_rapier), as long as\nthe simulation is run in `FixedUpdate` or `FixedPostUpdate`.\n\n## Getting Started\n\nFirst, add `bevy_transform_interpolation` to your dependencies in `Cargo.toml`:\n\n```toml\n[dependencies]\nbevy_transform_interpolation = \"0.2\"\n```\n\nTo enable `Transform` interpolation, add the `TransformInterpolationPlugin` to your app:\n\n```rust\nuse bevy::prelude::*;\nuse bevy_transform_interpolation::prelude::*;\n\nfn main() {\n    App::new()\n        .add_plugins((DefaultPlugins, TransformInterpolationPlugin::default()))\n        // ...other plugins, resources, and systems\n        .run();\n}\n```\n\nBy default, interpolation is only performed for entities with the `TransformInterpolation` component:\n\n```rust\nfn setup(mut commands: Commands) {\n    // Interpolate the entire transform: translation, rotation, and scale.\n    commands.spawn((\n        Transform::default(),\n        TransformInterpolation,\n    ));\n}\n```\n\nNow, any changes made to the `Transform` of the entity in `FixedPreUpdate`, `FixedUpdate`, or `FixedPostUpdate`\nwill automatically be interpolated in between fixed timesteps.\n\nIf you want *all* entities with a `Transform` to be interpolated by default, you can use\n`TransformInterpolationPlugin::interpolate_all()`:\n\n```rust\nfn main() {\n    App::new()\n        .add_plugins(TransformInterpolationPlugin::interpolate_all())\n        // ...\n        .run();\n}\n```\n\n## Advanced Usage\n\nFor a lot of applications, the functionality shown in the Getting Started guide might be all you need!\nHowever, `bevy_transform_interpolation` has a lot more to offer:\n\n- Granularly ease individual properties of the transform with `TranslationInterpolation`, `RotationInterpolation`, and `ScaleInterpolation`.\n- Opt out of transform easing for individual entities with `NoTranslationEasing`, `NoRotationEasing`, and `NoScaleEasing`.\n- Use extrapolation instead of interpolation with the `TransformExtrapolationPlugin` and its related components.\n- Use Hermite interpolation for more natural and accurate movement with the `TransformHermiteEasingPlugin`.\n- Implement custom easing backends for your specific needs.\n\n## How Does It Work?\n\nInternally, `bevy_transform_interpolation` simply maintains components that store the `start` and `end` of the interpolation.\nFor example, translation uses the following component for easing the movement:\n\n```rust\npub struct TranslationEasingState {\n    pub start: Option\u003cVec3\u003e,\n    pub end: Option\u003cVec3\u003e,\n}\n```\n\nThe states are updated by the `TransformInterpolationPlugin` or `TransformExtrapolationPlugin`\ndepending on whether the entity has `TransformInterpolation` or `TransformExtrapolation` components.\n\nIf interpolation is used:\n\n- In `FixedFirst`, `start` is set to the current `Transform`.\n- In `FixedLast`, `end` is set to the current `Transform`.\n\nIf extrapolation is used:\n\n- In `FixedLast`, `start` is set to the current `Transform`, and `end` is set to the `Transform` predicted based on velocity.\n\nAt the start of the `FixedFirst` schedule, the states are reset to `None`. If the `Transform` is detected to have changed\nsince the last easing run but *outside* of the fixed timestep schedules, the easing is also reset to `None` to prevent overwriting the change.\n\nThe actual easing is performed in `RunFixedMainLoop`, right after `FixedMain`, before `Update`.\nBy default, linear interpolation (`lerp`) is used for translation and scale, and spherical linear interpolation (`slerp`)\nis used for rotation.\n\nHowever, thanks to the modular and flexible architecture, other easing methods can also be used.\nThe `TransformHermiteEasingPlugin` provides an easing backend using Hermite interpolation,\noverwriting the linear interpolation for specific entities with the `NonlinearTranslationEasing`\nand `NonlinearRotationEasing` marker components. Custom easing solutions can be implemented using the same pattern.\n\n## Supported Bevy Versions\n\n| `bevy`  | `bevy_transform_interpolation` |\n| ------- | ------------------------------ |\n| 0.17    | 0.3                            |\n| 0.16    | 0.2                            |\n| 0.15    | 0.1                            |\n\n## License\n\n`bevy_transform_interpolation` is free and open source. All code in this repository is dual-licensed under either:\n\n- MIT License ([LICENSE-MIT](/LICENSE-MIT) or \u003chttp://opensource.org/licenses/MIT\u003e)\n- Apache License, Version 2.0 ([LICENSE-APACHE](/LICENSE-APACHE) or \u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e)\n\nat your option.\n","funding_links":["https://github.com/sponsors/Jondolf"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjondolf%2Fbevy_transform_interpolation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjondolf%2Fbevy_transform_interpolation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjondolf%2Fbevy_transform_interpolation/lists"}