You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RealityKit中如何在参考图像未追踪时暂停对应视频?

解决AR参考图像追踪状态对应视频播放/暂停的问题

你的核心问题是用了单个全局AVPlayer实例,所有参考图像的视频都共用它,自然没法单独控制每个视频的状态。要实现精准控制,得给每个检测到的参考图像分配独立的AVPlayer,并建立锚点与播放器的映射关系。

具体实现步骤:

  1. 添加锚点与播放器的映射字典
    在Coordinator里新增一个字典,用ARAnchor的唯一标识符作为key,对应每个视频的AVPlayer:
class Coordinator: NSObject, ARSessionDelegate {
    var parent: ARViewContainer
    // 存储每个锚点对应的AVPlayer
    var anchorPlayerMap: [UUID: AVPlayer] = [:]
    
    init(parent: ARViewContainer) {
        self.parent = parent
    }
    // ... 其他代码
}
  1. 修改视频节点创建逻辑,生成独立播放器
    修改createdVideoPlayerNodeFor方法,每次创建新的AVPlayer实例,并存入映射字典:
func createdVideoPlayerNodeFor(_ target: ARReferenceImage, anchorID: UUID) -> ModelEntity {
    var videoPlane = ModelEntity()
    guard let targetName = target.name,
          let validURL = Bundle.main.url(forResource: targetName, withExtension: "mp4") else {
        return videoPlane
    }
    // 为当前参考图像创建独立的AVPlayer
    let player = AVPlayer(url: validURL)
    player.play()
    // 将播放器存入字典,关联锚点ID
    anchorPlayerMap[anchorID] = player
    
    let videoMaterial = VideoMaterial(avPlayer: player)
    videoPlane = ModelEntity(mesh: .generatePlane(width: Float(target.physicalSize.width), depth: Float(target.physicalSize.height)), materials: [videoMaterial])
    print(target.name as Any)
    return videoPlane
}

同时更新didAdd anchors方法,传入锚点的identifier:

func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
    for anchor in anchors {
        guard let validAnchor = anchor as? ARImageAnchor else { continue }
        let anchorEntity = AnchorEntity(anchor: validAnchor)
        // 传入锚点ID,绑定对应的播放器
        anchorEntity.addChild(createdVideoPlayerNodeFor(validAnchor.referenceImage, anchorID: validAnchor.identifier))
        parent.arView.scene.addAnchor(anchorEntity)
    }
}
  1. 精准处理追踪状态更新
    在didUpdate anchors方法中,遍历所有更新的锚点,根据ID找到对应的播放器,控制播放/暂停:
func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
    for anchor in anchors {
        guard let validAnchor = anchor as? ARImageAnchor,
              let player = anchorPlayerMap[validAnchor.identifier] else {
            continue
        }
        if validAnchor.isTracked {
            if player.timeControlStatus != .playing {
                player.play()
                print("播放:\(validAnchor.name ?? "未知图像")")
            }
        } else {
            if player.timeControlStatus == .playing {
                player.pause()
                print("暂停:\(validAnchor.name ?? "未知图像")")
            }
        }
    }
}
  1. 处理锚点移除的情况(可选但推荐)
    当参考图像完全丢失被移除时,暂停对应播放器并清理字典,避免内存泄漏:
func session(_ session: ARSession, didRemove anchors: [ARAnchor]) {
    for anchor in anchors {
        guard let validAnchor = anchor as? ARImageAnchor,
              let player = anchorPlayerMap[validAnchor.identifier] else {
            continue
        }
        player.pause()
        anchorPlayerMap.removeValue(forKey: validAnchor.identifier)
        print("移除并暂停:\(validAnchor.name ?? "未知图像")")
    }
}

关键说明:

  • 每个参考图像对应独立的AVPlayer,通过锚点的UUID唯一标识,确保精准控制
  • 加入了播放状态判断,避免重复调用play/pause导致的异常
  • 处理锚点移除逻辑,减少内存占用

内容的提问来源于stack exchange,提问作者user1207524

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 11:55:25