Unity AR:用GameObject预制体替换ARPlane并支持ARAnchor
解决方案:用ARAnchor绑定3D物体适配ARPlane
原代码的问题在于没关联ARAnchor,也没处理ARPlane的动态更新,而且缩放计算没考虑物体原始尺寸。按下面的步骤改:
- 给目标ARPlane创建ARAnchor,把3D物体作为Anchor的子物体,这样Anchor会自动追踪平面的位置/旋转变化
- 基于物体原始尺寸计算缩放,避免缩放失真
- 订阅ARPlane的更新事件,实时调整3D物体的大小
完整代码示例:
using UnityEngine; using UnityEngine.XR.ARFoundation; public class PlaneObjectPlacer : MonoBehaviour { [SerializeField] private ARPlaneManager planeManager; [SerializeField] private GameObject objectToPlacePrefab; private GameObject placedObject; private ARAnchor planeAnchor; private Vector3 originalObjectScale; void Awake() { // 提前获取预制体的原始尺寸 if (objectToPlacePrefab != null) { originalObjectScale = objectToPlacePrefab.transform.localScale; } // 订阅平面检测和更新事件 planeManager.planesChanged += OnPlanesChanged; } void OnPlanesChanged(ARPlanesChangedEventArgs args) { // 处理新检测到的平面 foreach (var plane in args.added) { PlaceObjectOnTrackedPlane(plane); } // 处理平面更新(比如扫描范围扩大后尺寸变化) foreach (var plane in args.updated) { if (planeAnchor != null && planeAnchor.plane == plane) { UpdateObjectScale(plane); } } } void PlaceObjectOnTrackedPlane(ARPlane plane) { // 避免重复创建 if (placedObject != null) return; // 创建绑定到该平面的ARAnchor planeAnchor = plane.GetComponent<ARAnchor>(); if (planeAnchor == null) { planeAnchor = plane.gameObject.AddComponent<ARAnchor>(); } // 实例化3D物体并设置为Anchor的子物体 placedObject = Instantiate(objectToPlacePrefab, planeAnchor.transform); // 初始化位置、旋转和缩放 placedObject.transform.localPosition = Vector3.zero; placedObject.transform.localRotation = Quaternion.identity; UpdateObjectScale(plane); } void UpdateObjectScale(ARPlane plane) { if (placedObject == null || originalObjectScale == Vector3.zero) return; // 根据平面尺寸和物体原始尺寸计算缩放比例 Vector2 planeSize = plane.size; Vector3 scale = new Vector3( planeSize.x / originalObjectScale.x, 1f, // 保持Y轴缩放不变,按需调整 planeSize.y / originalObjectScale.z ); placedObject.transform.localScale = scale; } void OnDestroy() { // 取消订阅避免内存泄漏 if (planeManager != null) { planeManager.planesChanged -= OnPlanesChanged; } } }
关键说明:
- ARAnchor绑定:ARAnchor会自动关联到所属的ARPlane,当平面的位置、旋转或大小更新时,Anchor会同步变化,子物体自然跟着更新
- 缩放计算:用平面的实际尺寸除以物体的原始尺寸,确保3D物体刚好覆盖平面区域,不会因为物体本身初始尺寸导致缩放错误
- 事件订阅:通过
planesChanged事件处理新平面和平面更新,保证物体始终适配最新的平面数据 - 避免重复创建:加判断确保每个场景只创建一个物体(如果需要多个平面都创建,去掉判断即可)
使用时记得:
- 把ARPlaneManager组件拖到
planeManager字段 - 把你的3D物体预制体拖到
objectToPlacePrefab字段 - 确保ARSession和ARSessionOrigin已经在场景中
内容的提问来源于stack exchange,提问作者Grandma Kisses
相关产品推荐
相关产品推荐

