【问题标题】:Placing Furniture on drag in AR Core在 AR Core 中拖动家具
【发布时间】:2018-04-24 07:45:17
【问题描述】:

我是 Unity 的 ARCore 新手。我的同事已经在 iOS 上制作了这个应用程序。但是我在拖动对象并将其设置在某个位置时遇到了一些问题。您也可以用 2 个手指旋转它。在这里,我给出了 m 拖动的 ARKit 等效代码。谁能帮我在 AR Core 上做同样的事情

switch (Input.touchCount) {
  case 1:
    if (touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Moved) {
      var screenPosition = Camera.main.ScreenToViewportPoint(touch.position);
      ARPoint point = new ARPoint {
        x = screenPosition.x,
        y = screenPosition.y
      };

      // prioritize reults types
      ARHitTestResultType[] resultTypes = {
        //ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent, 
        // if you want to use infinite planes use this:
        ARHitTestResultType.ARHitTestResultTypeExistingPlane,
        ARHitTestResultType.ARHitTestResultTypeHorizontalPlane, 
        ARHitTestResultType.ARHitTestResultTypeFeaturePoint
      };

      foreach (ARHitTestResultType resultType in resultTypes) {
        if (HitTestWithResultType(point, resultType)) {
          return;
        }
      }
    }
    break;

  case 2:
    if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Ended) {
      Vector2 direction = touch.deltaPosition;

      float yAngleIncrementVal = touch.deltaPosition.magnitude;
      Vector3 currentRotation = transform.rotation.eulerAngles;

      if (direction.x > 0) {
        currentRotation.y += (yAngleIncrementVal * rotationScale);
      }
      else {
        currentRotation.y -= (yAngleIncrementVal * rotationScale);
      }

      transform.rotation = Quaternion.Euler(currentRotation);
    }

    break;
  }
}

此脚本将附加到将在平面上移动的游戏对象。如何拖动游戏对象并更新锚点以使其保持在平面上。谢谢你

【问题讨论】:

    标签: unity3d arcore


    【解决方案1】:

    我几乎在做同样的事情,这是我自己代码的简化版本:

    case 1:
        if (Input.GetTouch(0).phase == TouchPhase.Began)
        {
            touchOffset = ARCamera.WorldToScreenPoint(gameObject.position) - new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, 0);
        }
    
        RaycastHit hit;
        LayerMask layers = (1 << LayerMask.NameToLayer(layersOfGroundObjects))
        Ray ray = ARCamera.ScreenPointToRay(Input.GetTouch(0).position + new Vector2(mouseOffset.x, mouseOffset.y));
        if (!ClickedOnUI && Physics.Raycast(ray, out hit, Mathf.Infinity, layers))
        {
            if(Input.GetTouch(0).phase == TouchPhase.Began)
            {
                touchOffset = hit.point - gameObject.position;
            }
    
            if (Input.GetTouch(0).phase == TouchPhase.Moved)
            {
                gameObject.position = hit.point - touchOffset ;
            }
        }
    case 2:
        float currentTouchDistance = Vector2.Distance(touches[0].position, touches[1].position);
        float diff_y = touches[0].position.y - touches[1].position.y;
        float diff_x = touches[0].position.x - touches[1].position.x;
        float currentTouchAngle = Mathf.Atan2(diff_y, diff_x) * Mathf.Rad2Deg;
    
        if (isFirstFrameWithTwoTouches)
        {
            cachedTouchDistance = currentTouchDistance;
            cachedTouchAngle = currentTouchAngle;
            isFirstFrameWithTwoTouches = false;
        }
    
        float angleDelta = currentTouchAngle - cachedTouchAngle;
        float scaleMultiplier = (currentTouchDistance / cachedTouchDistance);
        float scaleAmount = cachedAugmentationScale * scaleMultiplier;
        float scaleAmountClamped = Mathf.Clamp(scaleAmount, scaleRangeMin, scaleRangeMax);
    
        if (enableRotation)
        {
            gameObject.localEulerAngles = cachedAugmentationRotation - new Vector3(0, angleDelta * 3f, 0);
        }
        if (enableRotation && enableScaling)
        {
            gameObject.localScale = new Vector3(scaleAmountClamped, scaleAmountClamped, scaleAmountClamped);
        }
    

    我还使用了一个 touchOffset,它是距离用户单击开始拖动的对象的枢轴(位置)的距离。每次拖动时,我都会将该偏移量应用于最终位置。它使拖动感觉更加自然。我还在我自己的代码中更多地使用它,因此它对我来说非常重要,但这与这个问题无关,所以我删除了其余的代码。

    此外,我使用了许多层作为地面,因为我可以将家具放置在 ARCore 跟踪平面以外的更多表面上。如果你只关心被跟踪的平面,那么要么为它分配一个层,要么使用 ARCore 的光线投射而不是 Unity 的光线投射。或者只是使用我的Eazy ARCore Interface 插件,它可以同时做到这两个(使用层来跟踪平面,并通过对多个表面进行光线投射使事情变得更容易)

    【讨论】:

    • 谢谢你,我会在我完成实施后告诉你结果
    • 我可以只检测 1 架飞机吗?我只想要地面。不是任何其他表面
    • 你的意思是ARCore检测到的跟踪飞机?是的当然。您可以手动为其设置图层,也可以使用ARCore raycasting。如果您使用的是 Eazy ARCore 界面,那么对于图层,请使用:LayerMask layers = 1 &lt;&lt; EazyARCoreInterface.TrackedPlaneLayer;
    • ARCore 检测到多层我只是希望它检测到地面而不是其他任何东西
    • ARCore 将检测所有水平面。例如,如果您想排除在桌子上检测到的飞机并只取实际地面上的飞机,您必须为此编写自己的逻辑。 ARCore 无法自动区分它们。但是,由于没有足够的可用数据,我不太确定如何实现这样的目标。也许您总是可以选择 y 值最低的飞机,前提是您事先知道要扫描的任何东西都不会低于实际地面
    猜你喜欢
    • 2021-12-15
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多