Realitykit Entity Synchronization Is Always Nil

RealityKit ARkit : find an anchor (or entity) from raycast - always nil

I finally manage to found a solution :

My ModelEntity (anchored) had to have a collision shape !

So after adding simply entity.generateCollisionShapes(recursive: true).

This is how I generate a simple box :


let box: MeshResource = .generateBox(width: width, height: height, depth: length)
var material = SimpleMaterial()
material.tintColor = color
let entity = ModelEntity(mesh: box, materials: [material])
entity.generateCollisionShapes(recursive: true) // Very important to active collisstion and hittesting !
return entity

and so after that we must tell the arView to listen to gestures :

arView.installGestures(.all, for: entity)

and finally :


@IBAction func onTap(_ sender: UITapGestureRecognizer){
let tapLocation = sender.location(in: arView)

if let hitEntity = arView.entity(
at: tapLocation
) {
print("touched")
print(hitEntity.name)
// touched !

return ;
}

}

Referencing RealityKit Component

In RealityKit (and RealityFoundation), you have to call a registerComponent() type method once for every custom component type that you want to use in your app, before you use it.

public static func registerComponent()

You don’t need to call this method for built-in component types, like CollisionComponent.

ValueComponent.registerComponent()

The same way you have to call registerSystem() type method to use a System (ECS pattern).


Solution

Seems that type casting to protocols that implement custom components isn't supported. Inexplicably why. Thus, use the following solution.

import UIKit
import RealityKit

protocol HasValueComponent { }

extension HasValueComponent where Self: Entity {
var val: Int {
get { components[ValueComponent.self]?.val ?? .zero }
set { components[ValueComponent.self]?.val = newValue }
}
}
struct ValueComponent: Component {
var val: Int
}

Primitive.swift

class Primitive: Entity, HasModel, HasValueComponent {

required init() {
super.init()

ValueComponent.registerComponent()

self.model = ModelComponent(mesh: .generateSphere(radius: 0.1),
materials: [SimpleMaterial()])
self.name = "model"
self.components.set(ValueComponent(val: 1234))
}
}

ViewController.swift

class ViewController: UIViewController {

var arView = ARView(frame: .zero)
let primitive = Primitive()

override func viewDidLoad() {
super.viewDidLoad()

arView.frame = self.view.frame
self.view.addSubview(arView)

let anchor = AnchorEntity()
anchor.addChild(self.primitive)
arView.scene.addAnchor(anchor)

if let model = arView.scene.findEntity(named: "model") {
print(model.components[ValueComponent.self]!.val) // 1234
print(model.components.has(ValueComponent.self)) // true
}
}
}

Apply a custom texture to Plane entity using RealityKit 2.0

You have to implement brand-new parameters instead of deprecated arguments:

func createBoard() {

let planeMesh = MeshResource.generatePlane(width: 1,
height: 1,
cornerRadius: 0.05)

var material = SimpleMaterial()

material.color = try! .init(tint: .white,
texture: .init(.load(named: "img", in: nil)))
material.metallic = .init(floatLiteral: 1.0)
material.roughness = .init(floatLiteral: 0.5)

let modelEntity = ModelEntity(mesh: planeMesh,
materials: [material])

let anchor = AnchorEntity()
anchor.addChild(modelEntity)
arView.scene.anchors.append(anchor)
}

Also, you can use the following syntax:

var material = SimpleMaterial()
material.color.texture = .init(try! .load(named: "img", in: nil))

If you need mode details, read this post.



Related Topics



Leave a reply



Submit