如何在visionOS的RealityKit沉浸式视图中绑定相机实现第一人称视角?
在visionOS + RealityKit中实现自定义透视相机(第一人称视角)的问题
我正在开发一款基于visionOS和RealityKit的第一人称游戏,尝试用透视相机实现第一人称效果,但测试时进入沉浸式视图后看不到相机视角。需求是把相机绑定到角色上,让角色在地图中移动。之前在ARView应用里通过设置arView.cameraMode = .nonAR实现过,但visionOS没有这个选项,请问怎么用透视相机?
测试代码如下:
struct Immersive: View { @Environment(AppModel.self) private var appModel var body: some View { RealityView { content in await content.add(makeModel()) } } func makeModel() async -> Entity { let gameScene = Entity() let sph = createSphereEntity(radius: 1, color: .red) let anchor = AnchorEntity() anchor.position = .init(x: 0, y: 0.5, z: -4) anchor.addChild(sph) gameScene.addChild(anchor) let sph2 = createSphereEntity(radius: 0.5, color: .brown) let anchor2 = AnchorEntity() anchor2.position = .init(x: 0.5, y: 0.0, z: -2) anchor2.addChild(sph2) gameScene.addChild(anchor2) let cameraEntity = Entity() let cameraPosition: SIMD3<Float> = [3, -7, -6] cameraEntity.look(at: sph2.position, from: cameraPosition, relativeTo: nil) cameraEntity.components.set(PerspectiveCameraComponent()) gameScene.addChild(cameraEntity) return gameScene } }
解决方案
- 启用自定义相机模式:visionOS的RealityView默认使用头部追踪的系统相机,必须显式指定
cameraMode: .custom才能让自定义相机生效。修改RealityView的初始化代码:
RealityView { content in await content.add(makeModel()) } cameraMode: .custom
- 调整相机位置与朝向:原代码中相机位置
[3, -7, -6]偏移过大,可能超出可视范围。建议先设置贴近人眼的高度,再调整朝向:
let cameraEntity = Entity() // 模拟人眼高度,位置在场景原点上方1.6米 cameraEntity.position = SIMD3<Float>(0, 1.6, 0) cameraEntity.components.set(PerspectiveCameraComponent()) // 让相机看向场景中的目标物体(比如sph2) cameraEntity.look(at: sph2.position, from: cameraEntity.position, relativeTo: gameScene) gameScene.addChild(cameraEntity)
- 绑定相机到角色实体:要实现相机随角色移动,只需将相机作为角色实体的子节点,而非直接添加到gameScene。示例:
// 创建角色实体 let playerEntity = Entity() playerEntity.position = SIMD3<Float>(0, 0, 0) // 设置相机相对于角色的位置(头部位置) cameraEntity.position = SIMD3<Float>(0, 1.6, 0) playerEntity.addChild(cameraEntity) gameScene.addChild(playerEntity)
- 验证实体创建逻辑:确保
createSphereEntity函数正确生成可见的ModelEntity,避免因实体未正确初始化导致看不到内容:
func createSphereEntity(radius: Float, color: UIColor) -> ModelEntity { let mesh = MeshResource.generateSphere(radius: radius) let material = SimpleMaterial(color: color, isMetallic: false) return ModelEntity(mesh: mesh, materials: [material]) }
内容的提问来源于stack exchange,提问作者Damiano Miazzi
相关产品推荐
相关产品推荐

