Contents

Manipulating entities with solid collisions

Extend the capabilities of your app by using entities, components, and systems to maintain solid collisions when manipulating entities.

Overview

Set up an interaction using ManipulationComponent, ForceEffectComponent, and custom components that maintain solid collisions while manipulating entities. This sample shows how to create a proxy Entity that follows the manipulated entity using forces. Because it is moved with forces, the proxy bumps into solid objects as person drags the entity with their hand.

Configure the entity with a custom component

After configuring an entity with ManipulationComponent, it passes through other colliders while using the gesture. The entity ignores other colliders because its motion is guided by the person’s hand. To create an interaction where an entity respects collisions and forces during a gesture, this sample moves the visual components from the “real” entity to a “proxy” entity for the duration of the gesture. With the real entity invisible and the proxy entity visible, ForceEffectComponent applies forces to the proxy entity that move it toward the real entity. This creates an interaction where you can manipulate the entity, but it no longer passes through solid colliders.

An extension for the custom Component, ManipulateWithSolidCollisionsComponent, configures the entity for the interaction. This method first creates and places a proxy entity as a descendant of the real entity. Then it copies the real entity’s ModelComponent and GroundingShadowComponent onto the proxy.

For more information about the entity component system (ECS) in RealityKit, see Implementing systems for entities in a scene.

Modify entities at specific moments during a gesture

To run code at specific moments during a manipulation gesture for a specific entity use ManipulationEvents.WillBegin and ManipulationEvents.WillRelease. To subscribe to these events, the sample first subscribes to ComponentEvents.DidAdd inside the initializer for a custom system.

// Subscribe to an event for when the component is added.
scene.subscribe(to: ComponentEvents.DidAdd.self,
                componentType: ManipulateWithSolidCollisionsComponent.self,
                onDidAddManipulateWithSolidCollisionsComponent).store(in: &subscriptions)

When the custom component is added to an entity, the app subscribes to the manipulation events on the entity.

// Subscribe to manipulation events when ManipulateWithSolidCollisionsComponent is added to an entity.
event.entity.scene?.subscribe(to: ManipulationEvents.WillBegin.self,
                              on: event.entity,
                              onManipulationWillBegin).store(in: &subscriptions)
event.entity.scene?.subscribe(to: ManipulationEvents.WillRelease.self,
                              on: event.entity,
                              onManipulationWillRelease).store(in: &subscriptions)

When the manipulation gesture begins, the app hides the real entity and reveals the proxy. To do this, the app copies PhysicsBodyComponent, CollisionComponent, and OpacityComponent from the real entity to the proxy:

// Copy physics components from the real entity to the proxy.
if let physicsBody = event.entity.components[PhysicsBodyComponent.self] {
    proxy.components.set(physicsBody)
    event.entity.components.remove(PhysicsBodyComponent.self)
}
if var collision = event.entity.components[CollisionComponent.self] {
    collision.filter.group = ManipulateWithSolidCollisionsComponent.proxyGroup
    proxy.components.set(collision)
    event.entity.components.remove(CollisionComponent.self)
}
if let opacity = event.entity.components[OpacityComponent.self] {
    proxy.components.set(opacity)
}
event.entity.components[OpacityComponent.self]?.opacity = 0

The inverse operations occur when a person releases the entity and the app transfers the components back to the real entity.

Use forces to move the entity with realistic physics

During the manipulation gesture, a custom System runs code each frame to apply a ForceEffectComponent to the real entity. ConstantRadialForceEffect attracts physics bodies to its center. DragForceEffect applies a force opposite to an entity’s direction of motion. Together these forces move the proxy entity toward the real entity during the manipulation gesture.

Additionally, configure each ForceEffect with a mask so that forces are only applied to entities that belong to a particular group.

// `ConstantRadialForce` will attract entities toward its center.
// This force will cause the proxy entity to move toward the real entity.
let constantForceEffect = ConstantRadialForceEffect(
    strength: strength * strengthMultiplier,
)

// Apply a drag force to avoid orbiting.
// Without this force, the proxy entity will be difficult to control.
let dragForceEffect = DragForceEffect(strength: strength)

// Set the `ForceEffectComponent` on the real entity.
entity.components.set(ForceEffectComponent(effects: [
    // Use a collision group as a mask to only affect colliders in the group.
    ForceEffect(effect: constantForceEffect, mask: ManipulateWithSolidCollisionsComponent.proxyGroup),
    ForceEffect(effect: dragForceEffect, mask: ManipulateWithSolidCollisionsComponent.proxyGroup)
]))

See Also

RealityKit and Reality Composer Pro