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

如何自动将世界原点设为地板新点并绑定3D模型?AnchorEntity失效排查

解决方案

一、修复AnchorEntity未激活及模型不显示问题

你的代码里AnchorEntity未激活(isActive=false)的核心原因是ARKit还没检测到符合条件的地板平面(满足minimumBounds: [0.5, 0.5]的水平地板),模型绑定到未激活的锚点自然不会显示。可以从以下几点调整:

  1. 降低平面检测的门槛,先移除minimumBounds参数,让ARKit更容易检测到地板:
let floorAnchorEntity = AnchorEntity(plane: [.horizontal], classification: [.floor])
floorAnchorEntity.name = "floor anchor entity"
arView.scene.addAnchor(floorAnchorEntity)
  1. 调整模型尺寸匹配需求:ARKit中1单位对应1米,加载模型后要将花瓶缩放到50cm高:
do {
    let modelEntity = try Entity.load(named: modelName)
    // 根据模型原始尺寸调整缩放,示例为缩放到原尺寸的50%
    modelEntity.scale = SIMD3<Float>(0.5, 0.5, 0.5)
    floorAnchorEntity.addChild(modelEntity)
} catch {
    assertionFailure("加载模型失败:\(error.localizedDescription)")
}
  1. 监听锚点激活状态,确认平面检测完成:
// 需提前声明:var cancellables = Set<AnyCancellable>()
floorAnchorEntity.isActivePublisher.sink { isActive in
    if isActive {
        print("地板锚点已激活,模型将显示")
    }
}.store(in: &cancellables)

二、实现三步异步流程的同步执行

步骤1(异步加载模型)和步骤2(检测地板点P)都是异步操作,可通过DispatchGroup或异步任务组合来等待两者完成后执行步骤3:

1. 封装异步加载模型方法

func loadModelAsync(named modelName: String) async throws -> ModelEntity {
    return try await Entity.load(named: modelName)
}

2. 封装检测初始原点正下方地板点P的方法

通过射线检测从初始原点向下寻找地板平面:

func getFloorPointBelowInitialOrigin() async -> SIMD3<Float>? {
    // 从屏幕中心发射射线(对准初始位置的地板)
    guard let raycastQuery = arView.makeRaycastQuery(
        from: arView.center,
        allowing: .estimatedPlane,
        alignment: .horizontal
    ) else { return nil }

    // 等待射线检测到符合条件的地板
    for await result in arView.session.raycast(query) {
        if result.target == .existingPlaneGeometry, result.classification == .floor {
            return result.worldTransform.columns.3.xyz
        }
    }
    return nil
}

3. 同步执行三个步骤

func executeWorkflow() async {
    var loadedModel: ModelEntity?
    var floorPointP: SIMD3<Float>?

    // 并行执行步骤1和步骤2
    async let modelTask = loadModelAsync(named: "Vase")
    async let pointTask = getFloorPointBelowInitialOrigin()

    do {
        loadedModel = try await modelTask
        // 调整模型到50cm高
        loadedModel?.scale = SIMD3<Float>(0.5, 0.5, 0.5)
    } catch {
        print("模型加载失败:\(error)")
    }
    floorPointP = await pointTask

    // 步骤3:将模型放置到点P
    guard let model = loadedModel, let p = floorPointP else {
        print("模型未加载完成或未检测到地板点P")
        return
    }

    // 创建绑定到世界坐标P的锚点,移步后模型会固定在该位置
    let worldAnchor = AnchorEntity(world: p)
    worldAnchor.addChild(model)
    arView.scene.addAnchor(worldAnchor)
}

调用说明

需要在异步上下文触发工作流:

Task {
    await executeWorkflow()
}

内容的提问来源于stack exchange,提问作者D.Park

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 01:45:27