2

So I asked a question a couple of days ago which Andy Jazz kindly answered. So I have been playing with the answer, and although I was able to implement a solution, it is incomplete because the method he used, was findEntity(named:) using RealityKit. While I used Reality Composer on my own answer.

Problem #1: findEntity(named:) method doesn't work on Reality Composer when you have multiple objects. So I arrived at the realization the using the findEntity(named:) method doesn't work. Because all the objects within the scene are named "simpBld_root", it doesn't work to trigger what I want to trigger.

Problem #2: When using the parenting notation, I am doing a trial and error because I don't really understand what is what. How can I call each object? This is also a consequence of my own inability to correctly understand WHAT to call from Reality Composer because I don't think I really understand how the parenting notation applies in reality composer. The picture below is the Scene I am working printed on the console.

enter image description here

Below is an example I made work, where instead of Andy's solution for findEntity(named: ) I used children[0]

This is the code I tried, when using the findEntity() method that did NOT work:

let redBoardModelEntity =  cubesAnchor.redBoard?.findEntity(named: "simpBld_root") as! ModelEntity
let greenCubeModelEntity =  cubesAnchor.greenCube?.findEntity(named: "simpBld_root") as! ModelEntity
let blueCubeModelEntity =  cubesAnchor.blueCube?.findEntity(named: "simpBld_root") as! ModelEntity

And this is what I ended up with, that worked, meaning, it showed all the objects and the entire thing dragged together. [See pic below, followed by code]

enter image description here

import UIKit
import RealityKit

class ViewController: UIViewController {
    @IBOutlet var arView: ARView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
                
        let boxAnchor = try! Experience.loadBox()
        arView.scene.anchors.append(boxAnchor)            
    
        let cubesAnchor = try! Experience.loadCubes()
        arView.scene.anchors.append(cubesAnchor)
        print (cubesAnchor)
        cubesAnchor.actions.behavior.onAction = handleTapOnEntity(_:)            
        
        let redModel =  cubesAnchor.children[0].children[0]
                  
        let group = ModelEntity() as ModelEntity & HasCollision
        group.addChild(redModel)
        // group.addChild(blueCubeModelEntity)
        // group.addChild(greenCubeModelEntity)
        
        group.generateCollisionShapes(recursive: false)
        self.arView.installGestures(.all, for: group)
        
        let shape = ShapeResource.generateBox(width: 1, height: 1, depth: 1)
        let collision = CollisionComponent(shapes: [shape],
                                             mode: .trigger,                                               
                                           filter: .sensor)
        group.components.set(collision)
        
        let anchor = AnchorEntity()
        anchor.addChild(group)
        anchor.scale = [5,5,5]
        arView.scene.anchors.append(anchor)            
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0){
            // self.arView.scene.anchors.removeAll()
            let coneAnchor = try! Experience.loadCone()
            self.arView.scene.anchors.append(coneAnchor)
            coneAnchor.actions.behavior.onAction = handleTapOnEntity(_:)                    
            // print(cubesAnchor)                
        }                          
        
        boxAnchor.actions.behavior.onAction = handleTapOnEntity(_:)
            
        func handleTapOnEntity(_ entity: Entity?){
            guard let entity = entity else { return }
            
           // self.myEntity = entity
           // self.myEntity?.isEnabled = false    
        }            
    }
}
Andy Jazz
  • 49,178
  • 17
  • 136
  • 220

1 Answers1

1

Traversing children entities (nodes)

According to diagram, your models are called greenCube, redBoard and blueCube respectively. Thus, the simplest way to get any ModelEntity from Reality Composer's scene hierarchy is to apply findEntity(named:) method followed by access to its sub-children.

let model = cubesAnchor.findEntity(named: "greenCube")?.children[0] as! ModelEntity

...or, thanks to the Reality Composer's naming scheme:

let model = cubesAnchor.greenCube?.children[0] as! ModelEntity

Names greenCube, redBoard and blueCube are entities' names. All three models have a name simpBld_root. So, you can rename each ModelEntity if you like.

model.name = "Green_Cube_Model"

print(cubesAnchor.findEntity(named: "greenCube")!)

Result in Xcode's console:

▿ 'greenCube' : Entity, children: 1
  ⟐ Transform
  ⟐ SynchronizationComponent
  ▿ 'Green_Cube_Model' : ModelEntity         // New name
    ⟐ PhysicsBodyComponent
    ⟐ Transform
    ⟐ SynchronizationComponent
    ⟐ CollisionComponent
    ⟐ ModelComponent

Now you are able to get each ModelEntity via its unique name:

let green = cubesAnchor.findEntity(named: "Green_Cube_Model") as! ModelEntity

Or you can go through the chain of children.


Here's my code:

import UIKit
import RealityKit
    
class ViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        let scene = try! Experience.loadTwoBoxes()
        
        // MODEL 001 
        let model001 = scene.findEntity(named: "redCube")?.children[0] as! ModelEntity & HasPhysicsBody
        model001.position.y = 1.0
        model001.physicsBody = .init()
        model001.generateCollisionShapes(recursive: false)
        
        // MODEL 002       
        let forRenaming: Entity = scene.findEntity(named: "blueCube")!
        forRenaming.children[0].name = "Blue_Cube_Model"
        print(forRenaming)
    
        let model002 = scene.findEntity(named: "Blue_Cube_Model") as! ModelEntity & HasPhysicsBody
        model002.position.y = 1.0
        model002.physicsBody = .init()
        model002.generateCollisionShapes(recursive: false)

        arView.scene.anchors.append(scene)
    }
}
Andy Jazz
  • 49,178
  • 17
  • 136
  • 220