ARCore教程修改求助:识别平面后自动创建物体(无需触摸)
把ARCore从触摸创建改成自动识别平面就创建物体的修改方案
我帮你梳理下具体的修改步骤,分Unity和原生Android两种常见的ARCore开发场景来说,你可以对应自己的教程环境来调整:
一、Unity环境下的修改
ARCore Unity教程里一般会用到ARPlaneManager组件,还有处理触摸放置的脚本。要实现自动创建,核心就是把「触摸触发」换成「监听平面检测事件」:
先删掉触摸触发的代码块
找到原来处理触摸输入的部分,大概是这样的:if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) { if (arRaycastManager.Raycast(Input.GetTouch(0).position, hits, TrackableType.PlaneWithinPolygon)) { // 这里是原来创建物体的代码 Instantiate(yourPrefab, hitPose.position, hitPose.rotation); } }直接把这段触摸相关的判断删掉就行,不用再等用户触摸了。
监听平面检测事件,自动创建物体
推荐用事件监听的方式,更高效。在你的放置脚本里加这些代码:private ARPlaneManager _planeManager; private bool _hasSpawned = false; // 标记是否已经创建过,避免重复生成 void Start() { _planeManager = GetComponent<ARPlaneManager>(); // 监听新平面被识别出来的事件 _planeManager.planeAdded += OnNewPlaneDetected; } private void OnNewPlaneDetected(ARPlaneAddedEventArgs args) { // 只创建一次物体 if (!_hasSpawned) { // 拿新识别平面的中心作为放置位置 Pose planeCenter = args.plane.centerPose; Instantiate(yourPrefab, planeCenter.position, planeCenter.rotation); _hasSpawned = true; // 可选:创建完后可以关掉平面的显示和检测,省性能 _planeManager.SetTrackablesActive(false); } }要是不想用事件,也可以在
Update里实时检查已识别的平面数量:void Update() { if (!_hasSpawned && _planeManager.trackables.count > 0) { // 取第一个识别到的平面来放置 ARPlane firstPlane = _planeManager.trackables[0]; Instantiate(yourPrefab, firstPlane.centerPose.position, firstPlane.centerPose.rotation); _hasSpawned = true; _planeManager.enabled = false; // 关闭平面检测 } }可选优化
如果觉得平面中心位置不合适,也可以从摄像头中心向平面发射射线,取交点作为放置点,这样物体更靠近视野中心。
二、原生Android(Java/Kotlin)环境下的修改
原生ARCore教程里通常会在onTouchEvent里处理触摸创建,我们要把触发逻辑换成平面检测的回调:
移除触摸触发的代码
找到onTouchEvent里处理触摸创建的部分,大概是这样的:@Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (frame != null && isTracking) { for (HitResult hit : frame.hitTest(event)) { Trackable trackable = hit.getTrackable(); if (trackable instanceof Plane && ((Plane) trackable).isPoseInPolygon(hit.getHitPose())) { createAnchor(hit.getHitPose()); // 原来创建物体的方法 break; } } } return true; } return super.onTouchEvent(event); }把这段触摸处理的逻辑注释掉或者删掉。
监听平面更新事件
首先确保你的Activity/Fragment实现了Session.UpdateListener接口,然后在初始化Session的时候设置监听:session.setUpdateListener(this);接着实现
onTrackablesUpdated方法,在里面处理平面检测后的创建逻辑:private boolean hasSpawned = false; @Override public void onTrackablesUpdated(TrackableUpdateList<Trackable> updateList) { if (hasSpawned) return; // 已经创建过就直接返回 for (Trackable trackable : updateList.getAddedTrackables()) { if (trackable instanceof Plane) { Plane plane = (Plane) trackable; // 确保平面处于稳定追踪状态,避免位置不准 if (plane.getTrackingState() == TrackingState.TRACKING) { Pose planeCenter = plane.getCenterPose(); createAnchor(planeCenter); // 调用原来的创建物体方法 hasSpawned = true; // 可选:关闭平面检测,节省资源 getSession().getConfig().setPlaneFindingMode(Config.PlaneFindingMode.DISABLED); break; } } } }
几个关键提醒
- 一定要加重复创建的标记:比如
_hasSpawned,不然每识别一个新平面就会生成一个物体,场景里会一堆重复的。 - 检查平面追踪状态:只在平面处于
TRACKING状态时创建,避免平面还在初始化的时候放置,导致物体位置飘。 - 可选关闭平面检测:如果只需要创建一次物体,创建完成后关掉平面检测,既能省性能,也不会再触发新的创建逻辑。
内容的提问来源于stack exchange,提问作者user9802048
相关产品推荐
相关产品推荐

