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

Unity中ARCore家具拖拽旋转功能实现求助(附ARKit等效代码)

嘿,作为ARCore新手遇到这个问题太正常了——毕竟ARKit和ARCore的平面检测API确实有差异,我直接给你对应实现代码,再拆解下关键逻辑,你就能快速上手啦!

ARCore 实现物体拖拽定位+双指旋转功能

先给你完整的等效实现代码,你可以直接放到Unity脚本里挂载到目标物体上(记得确保场景里有ARCore的Session和ARPlaneManager组件哦):

using UnityEngine;
using GoogleARCore;

public class ARCoreObjectManipulation : MonoBehaviour
{
    // 控制是否允许拖拽物体
    public bool allowDrag = true;
    // 控制是否允许旋转物体
    public bool allowRotate = true;

    // 记录上一帧双指的夹角,用于计算旋转增量
    private float lastFingerAngle;
    // 记录拖拽时是否已经命中平面
    private bool isDragging = false;

    void Update()
    {
        if (Session.Status != SessionStatus.Tracking)
        {
            // ARCore未追踪到环境时不处理触摸操作
            return;
        }

        switch (Input.touchCount)
        {
            case 1:
                if (!allowDrag) break;
                
                Touch touch = Input.GetTouch(0);
                HandleSingleTouch(touch);
                break;

            case 2:
                if (!allowRotate) break;
                
                Touch touch1 = Input.GetTouch(0);
                Touch touch2 = Input.GetTouch(1);
                HandleDoubleTouch(touch1, touch2);
                break;
        }
    }

    private void HandleSingleTouch(Touch touch)
    {
        switch (touch.phase)
        {
            case TouchPhase.Began:
                // 发射射线检测AR平面
                TrackableHit hit;
                TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon;

                if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
                {
                    // 如果命中平面,标记开始拖拽
                    isDragging = true;
                }
                break;

            case TouchPhase.Moved:
                if (isDragging)
                {
                    TrackableHit hit;
                    TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon;

                    if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
                    {
                        // 将物体移动到射线命中的平面位置
                        transform.position = hit.Pose.position;
                        // 保持物体的朝向和平面一致(可选,根据需求调整)
                        transform.rotation = hit.Pose.rotation;
                    }
                }
                break;

            case TouchPhase.Ended:
            case TouchPhase.Canceled:
                // 触摸结束,停止拖拽
                isDragging = false;
                break;
        }
    }

    private void HandleDoubleTouch(Touch touch1, Touch touch2)
    {
        // 获取当前双指的位置
        Vector2 touch1Pos = touch1.position;
        Vector2 touch2Pos = touch2.position;

        // 计算当前双指的夹角
        float currentFingerAngle = Vector2.Angle(touch1Pos - touch2Pos, Vector2.right);

        // 只有当触摸处于移动阶段时才计算旋转增量
        if (touch1.phase == TouchPhase.Moved || touch2.phase == TouchPhase.Moved)
        {
            // 计算夹角变化量,作为旋转增量
            float angleDelta = currentFingerAngle - lastFingerAngle;
            
            // 将旋转增量应用到物体的Y轴(可以根据需求改成X或Z轴)
            transform.Rotate(Vector3.up, -angleDelta, Space.World);
        }

        // 更新上一帧的夹角记录
        lastFingerAngle = currentFingerAngle;
    }
}

关键逻辑拆解

  1. ARCore平面检测:用Frame.Raycast替代ARKit的ScreenToViewportPoint+ARPoint逻辑,这个方法会直接检测ARCore识别到的平面,返回命中点的Pose(位置+旋转)。
  2. 拖拽功能:单指触摸开始时检测平面,移动时持续更新物体位置到命中点,触摸结束后停止拖拽。
  3. 双指旋转:通过计算双指之间的夹角变化,将增量应用到物体的旋转轴上(这里用的是世界空间的Y轴,你可以根据需求调整)。

注意事项

  • 确保你的Unity项目已经导入了ARCore SDK,并且配置了正确的ARSession和ARPlaneManager。
  • 如果不需要物体和平面保持旋转一致,可以去掉transform.rotation = hit.Pose.rotation这一行,让物体保持自身初始朝向。
  • 可以根据需求调整旋转的轴(比如改成物体自身的Y轴,把Space.World换成Space.Self)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:19:25