How to impose an Impulse

Hi. Given an RC entity

var physicsBody = tappedObject.entity.components[PhysicsBodyComponent.self]! as PhysicsBodyComponent

how does one call

func applyImpulse(_ impulse: SIMD3<Float>, at position: SIMD3<Float>, relativeTo referenceEntity: Entity?)

to impose an impulse on the object? Or the real question is how does one obtain a physiceBody on the Model.Entity?

Thanks!

It looks like you're trying to work with physics in an entity-component system. To apply an impulse to an object and work with physics bodies in a Model.Entity, you can follow these steps:

// Assuming you have a reference to the tappedObject.entity and a PhysicsBodyComponent

// Get the physics body component from the entity
guard let physicsBody = tappedObject.entity.components[PhysicsBodyComponent.self] as? PhysicsBodyComponent else {
    fatalError("PhysicsBodyComponent not found on the entity")
}

// Define the impulse and position where you want to apply it
let impulse = SIMD3<Float>(x: 0.0, y: 10.0, z: 0.0)  // Adjust the values as needed
let position = SIMD3<Float>(x: 0.0, y: 0.0, z: 0.0)  // Adjust the values as needed

// Get the reference entity if needed (can be nil)
let referenceEntity: Entity? = nil

// Apply the impulse to the physics body
physicsBody.applyImpulse(impulse, at: position, relativeTo: referenceEntity)

In this example, replace PhysicsBodyComponent with the actual class or type name of your physics body component. Make sure you have the necessary methods and properties defined in your PhysicsBodyComponent class to properly apply the impulse.

Remember to adjust the impulse and position values according to your requirements. This code assumes that you have set up your entity-component system correctly, and that the PhysicsBodyComponent class has a method named applyImpulse(_:at:relativeTo:) for applying impulses.

If you're having trouble obtaining the physics body component on the entity, double-check your entity-component setup and ensure that the component is properly attached to the entity.

Thanks Henry, for such a thorough answer.

You illustrate the problem. The last line where you call applyImpulse on physicsBody results in "Value of type 'PhysicsBodyComponent' has no member 'applyImpulse'". That's the challenge I am trying to resolve. Upon what object is applyImpulse supposed to be called on if not physicsBody as you (and I) have defined:

guard let physicsBody = tappedObject.entity.components[PhysicsBodyComponent.self] as? PhysicsBodyComponent else {
    fatalError("PhysicsBodyComponent not found on the entity")
}

To further clarify, this is a gesture handler that shows the issue:

	func Throw(objToThrow: EntityTargetValue<TapGesture.Value>) {
        let entT = objToThrow.entity
        let comp = entT.components
        let pbc = comp[PhysicsBodyComponent.self]!
        let physicsBodComp = pbc as PhysicsBodyComponent  // Type casting is unnecessary as pbc is already a PhysicsBodyComponent
        let impulse = SIMD3<Float>(x: 0.0, y: 10.0, z: 0.0)
        let position = SIMD3<Float>(x: 0.0, y: 0.0, z: 0.0)
        let referenceEntity: Entity? = nil
        physicsBodComp.applyImpulse(impulse, at: position, relativeTo: referenceEntity);     // <<< error here
	}

Thanks!

Hello,

You illustrate the problem. The last line where you call applyImpulse on physicsBody results in "Value of type 'PhysicsBodyComponent' has no member 'applyImpulse'". That's the challenge I am trying to resolve. Upon what object is applyImpulse supposed to be called on if not physicsBody as you (and I) have defined

"applyImpulse" is a method on ModelEntity.

Given that, assuming your entity here truly is a ModelEntity, you can dynamically cast it as such, and then call applyImpulse, something like this:


SpatialTapGesture()
            .targetedToAnyEntity()
            .onEnded { value in
                                
                if let modelEntity = value.entity as? ModelEntity {
                    modelEntity.applyLinearImpulse([0, 2.5, 0], relativeTo: nil)
                }
                
            }

Thank you for raising this issue, please let me know if anything above is unclear!

@gchiste What if we have a transform with 3 ModelEntities inside in reality composer pro. Something like this:

and since the three model entities represent a single object, can I execute applyImpulse to the "transform" layer named Body or do I have to do it to each individual model entity? (those three nested ones)

Because I believe my transform layer called "Body" is technically an Entity, and not a ModelEntity, right?

Since the 3 entities are children of Body, applying anything to the parent should (will?) effect the entire thing. Will be easy enough to test, right?

@kevyk yes, but the issue was that applyLinearImpulse doesn't exists on the parent entity. I was able to get around it by doing this:

let parentEntityHasPhyics = parentEntity as? HasPhysicsBody {
  parentEntityHasPhyics.applyLinearImpulse(...) // now we can use applyLinearImpulse without getting a compile-time error
}
How to impose an Impulse
 
 
Q