如何检查实体是否已附加到EntityAnchor?

问题描述 投票:0回答:2

我想在 Entity 不仅加载而且已成功附加到 AnchorEntity 时运行一些函数。

现在我的实体正在异步加载。

func addModel(to planeAnchor: AnchorEntity) {
    Entity.loadAsync(named: "SomeUSDZModel")
        .sink { completion in
            switch completion {
            case .finished:
                print("Ok")
            case .failure(let error):
                print(error.localizedDescription)
            }
        } receiveValue: { model in
            // Entity should be added before the animation is started.
            planeAnchor.addChild(model)
            if let walkingAnimation = model.availableAnimations.first {
                model.playAnimation(walkingAnimation.repeat(duration: .infinity),
                                    transitionDuration: 1.25,
                                    blendLayerOffset: 0,
                                    separateAnimatedValue: false,
                                    startsPaused: false)

            }
            self.model = model
            
        }
        .store(in: &subscriptions)
        doSomething()
}

方法 doSomething() 过早触发。我想在一些条件检查后将其关闭。

swift arkit combine realitykit
2个回答
3
投票

我设法采取不同的方法来解决这个问题。

首先我创建了一个 AnchorEntity

let planeAnchor = AnchorEntity(
        plane: .horizontal,
        classification: .any,
        minimumBounds: [0.5,0.5]
    )

我立即将机器人添加到此锚点:

 robot = MegaRobot(anchorEntity: planeAnchor, arView: self, gameSettings: gameSettings)

此时,我保持动画暂停但激活。

现在我要订阅我的飞机上 AnimationEvents 的更改Anchor:

func observeAnchorState() {
        if let robot = robot {
            self.gameSettings.gameStatus = .planeSearching
            // 1. Subscribe to changes
            self.anchorEntitySubscribtion = self.scene.subscribe(
                to: SceneEvents.AnchoredStateChanged.self,
                on: planeAnchor) { anchored in
                    // 3. if the change is the desired one, perform extra setup
                    if anchored.isAnchored {
                        robot.robotMode()
                        robot.animationController?.resume()
                        robot.activateRobotDragging()
                        self.gameSettings.gameStatus = .positioning
                        DispatchQueue.main.async {
                            // 4. Remove subscriber if further observations are not needed
                            self.anchorEntitySubscribtion?.cancel()
                            self.anchorEntitySubscribtion = nil
                        }
                    }
                }
            // 2. add planeAnchor to the scene
            self.scene.anchors.append(planeAnchor)
        } else {
            print("Fail to load")
        }
    }

0
投票

基于@Jakub Gawecki ansswer,我想要一种轻松知道实体何时锚定的方法,以便我可以添加动画,而不必为每个订阅声明变量。

特定于

RealityKit

的代码
extension Entity {
    @MainActor
    func onAnchored(content: any RealityViewContentProtocol, _ completion: @escaping () -> ()) {
        assert(self.anchor != nil, "Should add the entity to an anchor first")

        if self.isAnchored {
            completion()
            return
        }

        var subscriptionWrapper: EventSubscriptionWrapper? = .init()
        subscriptionWrapper!.subscription = content.subscribe(
            to: SceneEvents.AnchoredStateChanged.self,
            on: self.anchor
        ) { anchor in
            if anchor.isAnchored {
                completion()
                DispatchQueue.main.async {
                    subscriptionWrapper?.subscription?.cancel()
                    subscriptionWrapper = nil
                }
            }
        }
    }

    /// We need a reference type in order to be able to use the subscription inside the callback
    fileprivate class EventSubscriptionWrapper {
        var subscription: EventSubscription? = nil
    }
}

用途:

entity.onAnchored(content) {
    print("Entity is anchored")
}
© www.soinside.com 2019 - 2024. All rights reserved.