How do I spin and add a linear force to an Entity loaded from Reality Composer?
Asked Answered
F

3

3

I've constructed a scene in Reality Composer that has a ball that starts the scene floating in the air. I'm attempting to programmatically throw the ball while simultaneously spinning it.

I tried to do this through behaviors in Reality Composer, but can't get both behaviors to work simultaneously, also, the ball immediately falls to the ground once I start the animation.

My second attempt was to forgo the behavior route and I attempted to do this programmatically, but I can not add a force, because the loaded ball is an Entity and not a ModelEntity. What am I doing wrong?

I want to spin the ball, apply a force and enable gravity simultaneously.

Fefeal answered 11/4, 2020 at 21:4 Comment(0)
I
4

To add a force you need the Entity to conform to HasPhysicsMotion. To see if your Entity imported from RC can have forces applied to it, check if (myEntity as? HasPhysics) returns nil or a value.

If that returns nil, make your own Entity subclass which has the HasPhysics protocol, and set your entity as a child of it. If you want it to collide with other things in your scene then you’ll also want HasCollision protocol.

All the things you mentioned can be achieved from this point!

Inscrutable answered 12/4, 2020 at 19:58 Comment(1)
maxxfrazer, can you please answer this: #70891255Honeysuckle
P
3

Use the following code to create a custom class Physics that conforms to RealityKit's physics protocols (for controlling mass, velocity and kinematics/dynamics mode).

Here's how physics protocols' conforming hierarchy looks like:

HasPhysics: HasPhysicsBody, HasPhysicsMotion
                   |
                   |- HasCollision: HasTransform

Here's a code:

import ARKit
import RealityKit

class Physics: Entity, HasPhysicsBody, HasPhysicsMotion {

    required init() {
        super.init()

        self.physicsBody = PhysicsBodyComponent(massProperties: .default, 
                                                      material: nil, 
                                                          mode: .kinematic)

        self.physicsMotion = PhysicsMotionComponent(linearVelocity: [0.1, 0, 0], 
                                                   angularVelocity: [1, 3, 5])
    }
}

Then create an instance of that class in ViewController:

class ViewController: UIViewController {

    @IBOutlet var arView: ARView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let physics = Physics()
        arView.backgroundColor = .darkGray

        let boxAnchor = try! Experience.loadBox()
        boxAnchor.steelBox?.scale = [5, 5, 5]

        let boxEntity = boxAnchor.children[0].children[0].children[0]
        boxEntity.name = "CUBE"

        print(boxEntity)

        let kinematicComponent: PhysicsBodyComponent = physics.physicsBody!
        let motionComponent: PhysicsMotionComponent = physics.physicsMotion!

        boxEntity.components.set(kinematicComponent)
        boxEntity.components.set(motionComponent)

        arView.scene.anchors.append(boxAnchor)
    }
}

enter image description here


Also, look at THIS POST to find out how to implement physics without custom Physics class.


enter image description here

Peptize answered 17/4, 2020 at 16:44 Comment(1)
Thank you for your help Andy.Fefeal
P
0

So to clarify, if you have your entity in the Reality Composer file set to participate in physics. You can then do

(myEntity as? HasPhysics)?.addForce(SIMD3(x: 0, y: 0, z: 1), relativeTo: myEntity.parent)
Prewar answered 10/5, 2023 at 11:2 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.