diff --git a/bevy_rapier3d/examples/ray_casting3.rs b/bevy_rapier3d/examples/ray_casting3.rs
index 50a27a4c..c6068117 100644
--- a/bevy_rapier3d/examples/ray_casting3.rs
+++ b/bevy_rapier3d/examples/ray_casting3.rs
@@ -80,12 +80,16 @@ fn cast_ray(
 ) {
     let window = windows.single();
 
-    let Some(cursor_position) = window.cursor_position() else { return; };
+    let Some(cursor_position) = window.cursor_position() else {
+        return;
+    };
 
     // We will color in read the colliders hovered by the mouse.
     for (camera, camera_transform) in &cameras {
         // First, compute a ray from the mouse position.
-        let Some(ray) = camera.viewport_to_world(camera_transform, cursor_position) else { return; };
+        let Some(ray) = camera.viewport_to_world(camera_transform, cursor_position) else {
+            return;
+        };
 
         // Then cast the ray.
         let hit = rapier_context.cast_ray(
diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs
index a7dd2384..52a7a696 100644
--- a/src/geometry/collider.rs
+++ b/src/geometry/collider.rs
@@ -3,9 +3,15 @@ use std::fmt;
 #[cfg(all(feature = "dim3", feature = "async-collider"))]
 use {crate::geometry::VHACDParameters, bevy::utils::HashMap};
 
-use bevy::prelude::*;
+use bevy::{
+    ecs::{
+        entity::{EntityMapper, MapEntities},
+        reflect::ReflectMapEntities,
+    },
+    prelude::*,
+    utils::HashSet,
+};
 
-use bevy::utils::HashSet;
 use rapier::geometry::Shape;
 use rapier::prelude::{ColliderHandle, InteractionGroups, SharedShape};
 
@@ -503,6 +509,44 @@ impl CollidingEntities {
 #[reflect(Component, PartialEq)]
 pub struct ColliderDisabled;
 
+/// Rigid body parent of the collider.
+///
+/// This is not meant to be set directly, this is controlled by bevy's hierarchy.
+///
+/// To change a colliders parent, set the [`Parent`] of the entity to a
+/// different rigid body or remove the parent to leave the collider unattached.
+#[derive(Component, Debug, Eq, PartialEq, Reflect)]
+#[reflect(Component, MapEntities, PartialEq)]
+pub struct ColliderParent(pub(crate) Entity);
+
+impl ColliderParent {
+    /// Gets the [`Entity`] ID of the rigid-body parent this collider is attached to.
+    ///
+    /// This may be the same entity as the collider.
+    pub fn get(&self) -> Entity {
+        self.0
+    }
+}
+
+impl FromWorld for ColliderParent {
+    fn from_world(_world: &mut World) -> Self {
+        Self(Entity::PLACEHOLDER)
+    }
+}
+
+impl MapEntities for ColliderParent {
+    fn map_entities(&mut self, entity_mapper: &mut EntityMapper) {
+        self.0 = entity_mapper.get_or_reserve(self.0);
+    }
+}
+
+impl std::ops::Deref for ColliderParent {
+    type Target = Entity;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
 /// We restrict the scaling increment to 1.0e-4, to avoid numerical jitter
 /// due to the extraction of scaling factor from the GlobalTransform matrix.
 pub fn get_snapped_scale(scale: Vect) -> Vect {
diff --git a/src/geometry/collider_impl.rs b/src/geometry/collider_impl.rs
index f526ecd8..212a77f7 100644
--- a/src/geometry/collider_impl.rs
+++ b/src/geometry/collider_impl.rs
@@ -172,7 +172,9 @@ impl Collider {
     /// Returns `None` if the index buffer or vertex buffer of the mesh are in an incompatible format.
     #[cfg(all(feature = "dim3", feature = "async-collider"))]
     pub fn from_bevy_mesh(mesh: &Mesh, collider_shape: &ComputedColliderShape) -> Option<Self> {
-        let Some((vtx, idx)) = extract_mesh_vertices_indices(mesh) else { return None; };
+        let Some((vtx, idx)) = extract_mesh_vertices_indices(mesh) else {
+            return None;
+        };
         match collider_shape {
             ComputedColliderShape::TriMesh => Some(
                 SharedShape::trimesh_with_flags(vtx, idx, TriMeshFlags::MERGE_DUPLICATE_VERTICES)
diff --git a/src/plugin/plugin.rs b/src/plugin/plugin.rs
index fc5aa295..0ca2e088 100644
--- a/src/plugin/plugin.rs
+++ b/src/plugin/plugin.rs
@@ -77,6 +77,13 @@ where
     /// See [`PhysicsSet`] for a description of these systems.
     pub fn get_systems(set: PhysicsSet) -> SystemConfigs {
         match set {
+            PhysicsSet::EveryFrame => (
+                systems::collect_collider_hierarchy_changes,
+                apply_deferred,
+                systems::sync_removals,
+            )
+                .chain()
+                .into_configs(),
             PhysicsSet::SyncBackend => (
                 // Run the character controller before the manual transform propagation.
                 systems::update_character_controls,
@@ -94,9 +101,10 @@ where
                 systems::init_rigid_bodies,
                 systems::init_colliders,
                 systems::init_joints,
-                systems::sync_removals,
-                // Run this here so the folowwing systems do not have a 1 frame delay.
+                systems::collect_collider_hierarchy_changes,
+                // Run this here so the following systems do not have a 1 frame delay.
                 apply_deferred,
+                systems::sync_removals,
                 systems::apply_scale,
                 systems::apply_collider_user_changes,
                 systems::apply_rigid_body_user_changes,
@@ -159,6 +167,9 @@ pub enum PhysicsSet {
     /// components and the [`GlobalTransform`] component.
     /// These systems typically run immediately after [`PhysicsSet::StepSimulation`].
     Writeback,
+    /// The systems responsible for responding to state like `Events` that get
+    /// cleared every 2 main schedule runs.
+    EveryFrame,
 }
 
 impl<PhysicsHooks> Plugin for RapierPhysicsPlugin<PhysicsHooks>
@@ -172,6 +183,10 @@ where
             .register_type::<Velocity>()
             .register_type::<AdditionalMassProperties>()
             .register_type::<MassProperties>()
+            .register_type::<ReadMassProperties>()
+            .register_type::<ColliderMassProperties>()
+            .register_type::<ColliderDisabled>()
+            .register_type::<RigidBodyDisabled>()
             .register_type::<LockedAxes>()
             .register_type::<ExternalForce>()
             .register_type::<ExternalImpulse>()
@@ -185,6 +200,7 @@ where
             .register_type::<Friction>()
             .register_type::<Restitution>()
             .register_type::<CollisionGroups>()
+            .register_type::<ColliderParent>()
             .register_type::<SolverGroups>()
             .register_type::<ContactForceEventThreshold>()
             .register_type::<Group>();
@@ -204,6 +220,7 @@ where
 
         // Add each set as necessary
         if self.default_system_setup {
+            app.configure_sets(PostUpdate, (PhysicsSet::EveryFrame,));
             app.configure_sets(
                 self.schedule.clone(),
                 (
@@ -216,7 +233,10 @@ where
             );
 
             // These *must* be in the main schedule currently so that they do not miss events.
-            app.add_systems(PostUpdate, (systems::sync_removals,));
+            app.add_systems(
+                PostUpdate,
+                Self::get_systems(PhysicsSet::EveryFrame).in_set(PhysicsSet::EveryFrame),
+            );
 
             app.add_systems(
                 self.schedule.clone(),
diff --git a/src/plugin/systems.rs b/src/plugin/systems.rs
index aadbf662..943c2fe0 100644
--- a/src/plugin/systems.rs
+++ b/src/plugin/systems.rs
@@ -15,11 +15,13 @@ use crate::pipeline::{CollisionEvent, ContactForceEvent};
 use crate::plugin::configuration::{SimulationToRenderTime, TimestepMode};
 use crate::plugin::{RapierConfiguration, RapierContext};
 use crate::prelude::{
-    BevyPhysicsHooks, BevyPhysicsHooksAdapter, CollidingEntities, KinematicCharacterController,
-    KinematicCharacterControllerOutput, MassModifiedEvent, RigidBodyDisabled,
+    BevyPhysicsHooks, BevyPhysicsHooksAdapter, ColliderParent, CollidingEntities,
+    KinematicCharacterController, KinematicCharacterControllerOutput, MassModifiedEvent,
+    RigidBodyDisabled,
 };
 use crate::utils;
-use bevy::ecs::system::{StaticSystemParam, SystemParamItem};
+use bevy::ecs::system::{StaticSystemParam, SystemParam, SystemParamItem};
+use bevy::hierarchy::HierarchyEvent;
 use bevy::prelude::*;
 use rapier::prelude::*;
 use std::collections::HashMap;
@@ -117,47 +119,217 @@ pub fn apply_scale(
     }
 }
 
-/// System responsible for applying changes the user made to a collider-related component.
-pub fn apply_collider_user_changes(
-    mut context: ResMut<RapierContext>,
-    config: Res<RapierConfiguration>,
-    (changed_collider_transforms, parent_query, transform_query): (
-        Query<
-            (Entity, &RapierColliderHandle, &GlobalTransform),
-            (Without<RapierRigidBodyHandle>, Changed<GlobalTransform>),
-        >,
-        Query<&Parent>,
-        Query<&Transform>,
-    ),
-
-    changed_shapes: Query<(&RapierColliderHandle, &Collider), Changed<Collider>>,
-    changed_active_events: Query<(&RapierColliderHandle, &ActiveEvents), Changed<ActiveEvents>>,
-    changed_active_hooks: Query<(&RapierColliderHandle, &ActiveHooks), Changed<ActiveHooks>>,
+fn find_child_colliders(
+    base_entity: Entity,
+    colliders: &Query<&Collider>,
+    rigid_bodies: &Query<&RigidBody>,
+    childrens: &Query<&Children>,
+
+    found: &mut Vec<Entity>,
+    possibilities: &mut Vec<Entity>,
+) {
+    found.clear();
+    possibilities.clear();
+    possibilities.push(base_entity);
+    while let Some(entity) = possibilities.pop() {
+        if rigid_bodies.contains(entity) {
+            continue;
+        }
+
+        if colliders.contains(entity) {
+            found.push(entity);
+        }
+
+        if let Ok(children) = childrens.get(entity) {
+            possibilities.extend(children.iter());
+        } else {
+            continue;
+        };
+    }
+}
+
+/// System responsible for detecting changes in the hierarchy that would
+/// affect the collider's parent rigid body.
+pub fn collect_collider_hierarchy_changes(
+    mut commands: Commands,
+
+    mut hierarchy_events: EventReader<HierarchyEvent>,
+    parents: Query<&Parent>,
+    childrens: Query<&Children>,
+    rigid_bodies: Query<&RigidBody>,
+    colliders: Query<&Collider>,
+    mut collider_parents: Query<&mut ColliderParent>,
+
+    mut found: Local<Vec<Entity>>,
+    mut possibilities: Local<Vec<Entity>>,
+) {
+    let parent_rigid_body = |mut entity: Entity| -> Option<Entity> {
+        loop {
+            if rigid_bodies.contains(entity) {
+                return Some(entity);
+            }
+
+            if let Ok(parent) = parents.get(entity) {
+                entity = parent.get();
+            } else {
+                return None;
+            }
+        }
+    };
+
+    for event in hierarchy_events.iter() {
+        match event {
+            HierarchyEvent::ChildAdded { child, .. } | HierarchyEvent::ChildMoved { child, .. } => {
+                let Some(rigid_body) = parent_rigid_body(*child) else {
+                    continue;
+                };
+                find_child_colliders(
+                    *child,
+                    &colliders,
+                    &rigid_bodies,
+                    &childrens,
+                    &mut found,
+                    &mut possibilities,
+                );
+
+                for collider in &found {
+                    let new_collider_parent = ColliderParent(rigid_body);
+                    if let Ok(mut collider_parent) = collider_parents.get_mut(*collider) {
+                        *collider_parent = new_collider_parent;
+                    } else {
+                        commands.entity(*collider).insert(new_collider_parent);
+                    }
+                }
+            }
+            HierarchyEvent::ChildRemoved { child, .. } => {
+                find_child_colliders(
+                    *child,
+                    &colliders,
+                    &rigid_bodies,
+                    &childrens,
+                    &mut found,
+                    &mut possibilities,
+                );
+                for collider in &found {
+                    if collider_parents.contains(*collider) {
+                        commands.entity(*collider).remove::<ColliderParent>();
+                    }
+                }
+            }
+        }
+    }
+}
+
+/// Collection of change queries for colliders.
+///
+/// Mainly used because bevy doesn't impl more than
+/// 16 parameters for a system.
+#[derive(SystemParam)]
+pub struct ColliderChanges<'w, 's> {
+    changed_collider_transforms: Query<
+        'w,
+        's,
+        (
+            Entity,
+            &'static RapierColliderHandle,
+            &'static GlobalTransform,
+        ),
+        (Without<RapierRigidBodyHandle>, Changed<GlobalTransform>),
+    >,
+    changed_collider_parents: Query<
+        'w,
+        's,
+        (&'static RapierColliderHandle, &'static ColliderParent),
+        Changed<ColliderParent>,
+    >,
+    changed_shapes:
+        Query<'w, 's, (&'static RapierColliderHandle, &'static Collider), Changed<Collider>>,
+    changed_active_events: Query<
+        'w,
+        's,
+        (&'static RapierColliderHandle, &'static ActiveEvents),
+        Changed<ActiveEvents>,
+    >,
+    changed_active_hooks:
+        Query<'w, 's, (&'static RapierColliderHandle, &'static ActiveHooks), Changed<ActiveHooks>>,
     changed_active_collision_types: Query<
-        (&RapierColliderHandle, &ActiveCollisionTypes),
+        'w,
+        's,
+        (&'static RapierColliderHandle, &'static ActiveCollisionTypes),
         Changed<ActiveCollisionTypes>,
     >,
-    changed_friction: Query<(&RapierColliderHandle, &Friction), Changed<Friction>>,
-    changed_restitution: Query<(&RapierColliderHandle, &Restitution), Changed<Restitution>>,
+    changed_friction:
+        Query<'w, 's, (&'static RapierColliderHandle, &'static Friction), Changed<Friction>>,
+    changed_restitution:
+        Query<'w, 's, (&'static RapierColliderHandle, &'static Restitution), Changed<Restitution>>,
     changed_collision_groups: Query<
-        (&RapierColliderHandle, &CollisionGroups),
+        'w,
+        's,
+        (&'static RapierColliderHandle, &'static CollisionGroups),
         Changed<CollisionGroups>,
     >,
-    changed_solver_groups: Query<(&RapierColliderHandle, &SolverGroups), Changed<SolverGroups>>,
-    changed_sensors: Query<(&RapierColliderHandle, &Sensor), Changed<Sensor>>,
-    changed_disabled: Query<(&RapierColliderHandle, &ColliderDisabled), Changed<ColliderDisabled>>,
+    changed_solver_groups: Query<
+        'w,
+        's,
+        (&'static RapierColliderHandle, &'static SolverGroups),
+        Changed<SolverGroups>,
+    >,
+    changed_sensors:
+        Query<'w, 's, (&'static RapierColliderHandle, &'static Sensor), Changed<Sensor>>,
+    changed_disabled: Query<
+        'w,
+        's,
+        (&'static RapierColliderHandle, &'static ColliderDisabled),
+        Changed<ColliderDisabled>,
+    >,
     changed_contact_force_threshold: Query<
-        (&RapierColliderHandle, &ContactForceEventThreshold),
+        'w,
+        's,
+        (
+            &'static RapierColliderHandle,
+            &'static ContactForceEventThreshold,
+        ),
         Changed<ContactForceEventThreshold>,
     >,
     changed_collider_mass_props: Query<
-        (&RapierColliderHandle, &ColliderMassProperties),
+        'w,
+        's,
+        (
+            &'static RapierColliderHandle,
+            &'static ColliderMassProperties,
+        ),
         Changed<ColliderMassProperties>,
     >,
+}
+
+/// System responsible for applying changes the user made to a collider-related component.
+pub fn apply_collider_user_changes(
+    mut context: ResMut<RapierContext>,
+    config: Res<RapierConfiguration>,
+
+    collider_changes: ColliderChanges,
+    parent_query: Query<&Parent>,
+    transform_query: Query<&Transform>,
 
     mut mass_modified: EventWriter<MassModifiedEvent>,
 ) {
     let scale = context.physics_scale;
+    let ColliderChanges {
+        changed_collider_transforms,
+        changed_collider_parents,
+        changed_shapes,
+        changed_active_events,
+        changed_active_hooks,
+        changed_active_collision_types,
+        changed_friction,
+        changed_restitution,
+        changed_collision_groups,
+        changed_solver_groups,
+        changed_sensors,
+        changed_disabled,
+        changed_contact_force_threshold,
+        changed_collider_mass_props,
+    } = collider_changes;
 
     for (entity, handle, transform) in changed_collider_transforms.iter() {
         if context.collider_parent(entity).is_some() {
@@ -175,6 +347,17 @@ pub fn apply_collider_user_changes(
         }
     }
 
+    for (handle, collider_parent) in changed_collider_parents.iter() {
+        if let Some(body_handle) = context.entity2body.get(&collider_parent.0).copied() {
+            let RapierContext {
+                ref mut colliders,
+                ref mut bodies,
+                ..
+            } = *context;
+            colliders.set_parent(handle.0, Some(body_handle), bodies);
+        }
+    }
+
     for (handle, shape) in changed_shapes.iter() {
         if let Some(co) = context.colliders.get_mut(handle.0) {
             let mut scaled_shape = shape.clone();
@@ -745,9 +928,10 @@ pub fn step_simulation<Hooks>(
 #[cfg(all(feature = "dim3", feature = "async-collider"))]
 pub fn init_async_colliders(
     mut commands: Commands,
-    meshes: Res<Assets<Mesh>>,
+    meshes: Option<Res<Assets<Mesh>>>,
     async_colliders: Query<(Entity, &Handle<Mesh>, &AsyncCollider)>,
 ) {
+    let Some(meshes) = meshes else { return };
     for (entity, mesh_handle, async_collider) in async_colliders.iter() {
         if let Some(mesh) = meshes.get(mesh_handle) {
             match Collider::from_bevy_mesh(mesh, &async_collider.0) {
@@ -768,12 +952,16 @@ pub fn init_async_colliders(
 #[cfg(all(feature = "dim3", feature = "async-collider"))]
 pub fn init_async_scene_colliders(
     mut commands: Commands,
-    meshes: Res<Assets<Mesh>>,
-    scene_spawner: Res<SceneSpawner>,
+    meshes: Option<Res<Assets<Mesh>>>,
+    scene_spawner: Option<Res<SceneSpawner>>,
     async_colliders: Query<(Entity, &SceneInstance, &AsyncSceneCollider)>,
     children: Query<&Children>,
     mesh_handles: Query<(&Name, &Handle<Mesh>)>,
 ) {
+    let Some(meshes) = meshes else { return };
+    let Some(scene_spawner) = scene_spawner else {
+        return;
+    };
     for (scene_entity, scene_instance, async_collider) in async_colliders.iter() {
         if scene_spawner.instance_is_ready(**scene_instance) {
             for child_entity in children.iter_descendants(scene_entity) {
@@ -935,6 +1123,8 @@ pub fn init_colliders(
                 context
                     .colliders
                     .insert_with_parent(builder, body_handle, &mut context.bodies);
+            commands.entity(entity).insert(ColliderParent(body_entity));
+
             if let Ok(mut mprops) = rigid_body_mprops.get_mut(body_entity) {
                 // Inserting the collider changed the rigid-body’s mass properties.
                 // Read them back from the engine.
@@ -956,6 +1146,7 @@ pub fn init_colliders(
         };
 
         commands.entity(entity).insert(RapierColliderHandle(handle));
+
         context.entity2collider.insert(entity, handle);
     }
 }
@@ -1180,6 +1371,7 @@ pub fn sync_removals(
     mut removed_sensors: RemovedComponents<Sensor>,
     mut removed_rigid_body_disabled: RemovedComponents<RigidBodyDisabled>,
     mut removed_colliders_disabled: RemovedComponents<ColliderDisabled>,
+    mut removed_collider_parents: RemovedComponents<ColliderParent>,
 
     mut mass_modified: EventWriter<MassModifiedEvent>,
 ) {
@@ -1308,6 +1500,17 @@ pub fn sync_removals(
         }
     }
 
+    for entity in removed_collider_parents.iter() {
+        if let Some(handle) = context.entity2collider.get(&entity) {
+            let RapierContext {
+                ref mut colliders,
+                ref mut bodies,
+                ..
+            } = *context;
+            colliders.set_parent(*handle, None, bodies);
+        }
+    }
+
     // TODO: what about removing forces?
 }
 
@@ -1684,6 +1887,7 @@ mod tests {
         app.add_plugins((
             HeadlessRenderPlugin,
             TransformPlugin,
+            HierarchyPlugin,
             TimePlugin,
             RapierPhysicsPlugin::<NoUserData>::default(),
         ));
@@ -1741,6 +1945,7 @@ mod tests {
         app.add_plugins((
             HeadlessRenderPlugin,
             TransformPlugin,
+            HierarchyPlugin,
             TimePlugin,
             RapierPhysicsPlugin::<NoUserData>::default(),
         ));
@@ -1815,6 +2020,149 @@ mod tests {
         }
     }
 
+    #[test]
+    fn collider_parent() {
+        let mut app = App::new();
+        app.add_plugins((
+            TransformPlugin,
+            HierarchyPlugin,
+            TimePlugin,
+            RapierPhysicsPlugin::<NoUserData>::default(),
+        ));
+
+        fn verify_collider_parent(
+            ctx: Res<RapierContext>,
+            colliders: Query<(Entity, Option<&ColliderParent>), With<Collider>>,
+            parents: Query<&Parent>,
+            bodies: Query<(), With<RigidBody>>,
+            names: Query<&Name>,
+        ) {
+            let row_length = 60;
+            let column_length = row_length / 4;
+            let column = |collider: &str, rapier: &str, component: &str, hierarchal: &str| {
+                println!(
+                    "{:<column_length$}| {:<column_length$}| {:<column_length$}| {:<column_length$}",
+                    collider, rapier, component, hierarchal,
+                );
+            };
+
+            column("collider", "rapier", "component", "hierarchal");
+            println!("{}", "-".repeat(row_length));
+            for (collider_entity, collider_parent) in &colliders {
+                let rapier_parent = ctx.collider_parent(collider_entity);
+                let collider_parent = collider_parent.map(|parent| parent.get());
+
+                let mut entity = collider_entity;
+                let mut hierarchal_parent = None;
+                loop {
+                    if bodies.contains(entity) {
+                        hierarchal_parent = Some(entity);
+                        break;
+                    }
+
+                    let Ok(parent) = parents.get(entity) else {
+                        break;
+                    };
+                    entity = parent.get();
+                }
+
+                let named = |entity: Option<Entity>| -> String {
+                    entity
+                        .map(|entity| {
+                            names
+                                .get(entity)
+                                .map(|name| name.as_str().to_owned())
+                                .unwrap_or(format!("{:?}", entity))
+                        })
+                        .unwrap_or("None".to_owned())
+                };
+                column(
+                    &named(Some(collider_entity)),
+                    &named(rapier_parent),
+                    &named(collider_parent),
+                    &named(hierarchal_parent),
+                );
+
+                assert_eq!(rapier_parent, collider_parent);
+                assert_eq!(rapier_parent, hierarchal_parent);
+            }
+        }
+
+        fn frame(mut frame: Local<u32>) {
+            *frame += 1;
+            println!("-- frame {} -----------", *frame);
+            println!();
+        }
+
+        app.add_systems(Last, (frame, verify_collider_parent).chain());
+
+        let self_parented = app
+            .world
+            .spawn((
+                Name::new("Self-parented"),
+                TransformBundle::default(),
+                RigidBody::Dynamic,
+                Collider::default(),
+            ))
+            .id();
+
+        let parent1 = app
+            .world
+            .spawn((
+                Name::new("Parent 1"),
+                TransformBundle::default(),
+                RigidBody::Dynamic,
+            ))
+            .id();
+
+        let parent2 = app
+            .world
+            .spawn((
+                Name::new("Parent 2"),
+                TransformBundle::default(),
+                RigidBody::Dynamic,
+            ))
+            .id();
+
+        let inbetween = app
+            .world
+            .spawn((Name::new("Inbetween"), TransformBundle::default()))
+            .id();
+
+        let child = app
+            .world
+            .spawn((
+                Name::new("Child collider"),
+                TransformBundle::default(),
+                Collider::default(),
+            ))
+            .id();
+
+        // Unnested
+        app.update();
+        app.world.entity_mut(self_parented).despawn_recursive();
+        app.world.entity_mut(child).set_parent(parent1);
+        app.update();
+        app.world.entity_mut(child).set_parent(parent2);
+        app.update();
+        app.world.entity_mut(child).remove_parent();
+        app.update();
+
+        // Nested
+        app.world.entity_mut(child).set_parent(inbetween);
+        app.update();
+        app.world.entity_mut(inbetween).set_parent(parent1);
+        app.update();
+        app.world.entity_mut(inbetween).set_parent(parent2);
+        app.update();
+        app.world.entity_mut(inbetween).remove_parent();
+        app.update();
+
+        app.world.entity_mut(inbetween).set_parent(parent1);
+        app.world.entity_mut(child).remove_parent();
+        app.update();
+    }
+
     // Allows run tests for systems containing rendering related things without GPU
     struct HeadlessRenderPlugin;