Collisions & Physics: Hello Physics Joints Component

We can create collections of entities that are linked together.

Overview

This is the last of the four main physics components for us to talk about. We can use physics joints to create collections or chains of objects linked together. There are a lot of possibilities, but let’s focus on the basic setup in this post.

  • We need a parent entity with a physics simulation component
  • We also need to add a Physics Joints component
  • We can add two or more child entities with physics bodies
  • Then we create pins to describe how the entities are linked
  • Create a joint from two pins
  • Lastly, add the joint to the simulation

This simple example will create two boxes that are linked together with a single joint. When we move one of them, the other will move with it.

We’ll look at more advanced uses in the future. For now, take a look at Lab 015 for an example with multiple joints.

Example Code

struct Example064: View {
    var body: some View {
        RealityView { content in

            // Set up a top level entity for the simulation and the joints component
            let jointsSimulation = Entity()
            jointsSimulation.components.set([PhysicsSimulationComponent(), PhysicsJointsComponent()])
            content.add(jointsSimulation)

            // Create some shapes and add them to the simulation
            let boxA = makeSampleBox(color: .stepRed)
            boxA.position.x = -0.1
            jointsSimulation.addChild(boxA)

            let boxB = makeSampleBox(color: .stepGreen)
            boxB.position.x = 0.1
            jointsSimulation.addChild(boxB)

            // Create a basic hinge
            let hingeOrientation = simd_quatf(from: [1, 0, 0], to: [0, 0, 1])

            // Create a pin for each box
            let pin1 = boxA.pins.set(
                named: "boxA_to_boxB_hinge",
                position: .zero,
                orientation: hingeOrientation
            )
            let pin2 = boxB.pins.set(
                named: "boxB_to_boxA_hinge",
                position: boxB.position(relativeTo: boxA),
                orientation: hingeOrientation
            )

            // Join the pins together as a joint
            let simpleJoint1 = PhysicsRevoluteJoint(pin0: pin1, pin1: pin2)

            // Add the joint to the simulation
            Task {
                try simpleJoint1.addToSimulation()
            }

        }
        .modifier(DragGestureImproved())
    }

    func makeSampleBox(color: UIColor) -> ModelEntity {
        let collision = CollisionComponent(shapes: [.generateBox(size: .init(repeating: 0.1))])
        let inputTarget = InputTargetComponent()
        var physicsBody = PhysicsBodyComponent()
        physicsBody.isAffectedByGravity = false

        let box = ModelEntity(
            mesh: .generateBox(size: 0.1),
            materials: [SimpleMaterial(color: color, isMetallic: false)])
        box.components.set([collision, inputTarget, physicsBody])

        return box
    }
}

Support our work so we can continue to bring you new examples and articles.

Download the Xcode project with this and many more examples from Step Into Vision.
Some examples are provided as standalone Xcode projects. You can find those here.

Questions or feedback?