在AR Core中放置家具

时间:2018-04-24 07:45:17

标签: unity3d arcore

我是Unity的ARCore新手。我的同事已经在iOS上制作了这个应用程序。但我在拖动对象并将其设置在某个位置时遇到一些问题。你也可以用两根手指旋转它。在这里,我给出了拖动的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;
  }
}

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

1 个答案:

答案 0 :(得分:0)

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

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插件,它可以同时执行这两个操作(使用跟踪平面的图层,并通过多个曲面的光线投射使事情变得更容易)