Exemple #1
0
    void TouchParty(GameObject showObject)
    {
        Touch touch;

        if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
        {
            return;
        }

        TrackableHit     hit;
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;


        if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
        {
            // destroy the 2D screenspace key
            m_keyCollectedUI.SetActive(false);


            // this probably doesn't need to be an array and loop but i kinda want to keep it for a minute...
            GameObject[] gameobjects = GameObject.FindGameObjectsWithTag("destroyable");
            foreach (GameObject g in gameobjects)
            {
                Destroy(g);
            }

            Object.Instantiate(showObject, m_firstObjectPos, m_firstObjectRot);

            m_applauseAudio.SetActive(true);
            m_confettiParticle.SetActive(true);
            m_thirdCreated = true;
        }
    }
Exemple #2
0
    void Update()
    {
        //Update ARCore planes
        UpdatePlanes();

        //Check if user clicked
        if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began && !IsPointerOverUIObject() && currentWheelIndex < 6)
        {
            Touch touch = Input.GetTouch(0);

            //Send ray to check if we hit a plane
            TrackableHit     hit;
            TrackableHitFlag flag = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

            if (Session.Raycast(firstPersonCamera.ScreenPointToRay(touch.position), flag, out hit))
            {
                //We hit a plane - add a wheel node
                //If this was a last node in this wheel - make Next button available
                if (wheels[currentWheelIndex].AddNode(hit.Point))
                {
                    uiController.SetNextButtonState(true);
                }
                uiController.SetUndoButtonState(true);
            }
        }

        //Update wheels
        foreach (NodeObject wheel in wheels)
        {
            wheel.UpdateLines();
        }

        Debug.Log(currentWheelIndex);
    }
Exemple #3
0
    void UpdateLastAndy()
    {
        TrackableHit     hit;
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

        Vector2 center = new Vector2(Screen.width / 2f, Screen.height / 2f);

        if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(center), raycastFilter, out hit))
        {
            foreach (PlaneAttachment andy in andys)
            {
                // if (hit.Plane != andy.m_AttachedPlane) {
                //   continue;
                // }

                // Andy should look at the hit point but still be flush with the plane.
                andy.transform.LookAt(hit.Point);
                andy.transform.rotation = Quaternion.Euler(0.0f,
                                                           andy.transform.rotation.eulerAngles.y, andy.transform.rotation.z);

                if (Vector3.Distance(hit.Point, andy.transform.position) > .1f)
                {
                    andy.GetComponent <Rigidbody>().velocity = andy.transform.forward.normalized * 1f;
                }
                else
                {
                    andy.GetComponent <Rigidbody>().velocity = Vector3.zero;
                }
            }
        }
    }
    void HandleTouchInput(int layerMask)
    {
        // One touch = paint a portal
        if (Input.touchCount == 1)
        {
            RaycastHit h;
            // First: does our touch intersect with an existing portal? If so, draw on that one instead of making a new one
            if (Physics.Raycast(cam.ScreenPointToRay(Input.GetTouch(0).position), out h, Mathf.Infinity, layerMask))
            {
                UpdatePixels(h);
            }
            else
            {
                // If not, then we just make a new one
                if (canPlacePortal)
                {
                    TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds |
                                                     TrackableHitFlag.PlaneWithinPolygon |
                                                     TrackableHitFlag.PointCloud;
                    TrackableHit hit;

                    if (Session.Raycast(cam.ScreenPointToRay(Input.GetTouch(0).position), raycastFilter, out hit))
                    {
                        PlacePortal(hit);
                        canPlacePortal = false;
                    }
                }
            }

            // Two touches = change which world is being painted
        }
        else if (Input.touchCount == 2)
        {
            if (canChangeWorld)
            {
                int curWorld = worldTracker.curWorld + 1;
                curWorld = curWorld % worldTracker.worlds.Length;
                worldTracker.curWorld = curWorld;
                canChangeWorld        = false;
            }

            // Three touches = delete all portals
        }
        else if (Input.touchCount == 3)
        {
            GameObject[] gameobjects = GameObject.FindGameObjectsWithTag("Portal");
            foreach (GameObject g in gameobjects)
            {
                Destroy(g);
            }
        }

        // No touches? Let the user switch worlds/clear/paint more portals
        else
        {
            canPlacePortal = true;
            canChangeWorld = true;
        }
    }
Exemple #5
0
 /// @cond EXCLUDE_FROM_DOXYGEN
 /// <summary>
 /// Constructs a TrackableHit.
 /// </summary>
 public TrackableHit(Vector3 point, Vector3 normal, float distance, TrackableHitFlag flags, TrackedPlane plane)
 {
     Point    = point;
     Normal   = normal;
     Distance = distance;
     Flags    = flags;
     Plane    = plane;
 }
Exemple #6
0
    void MakeObjectNow(GameObject prefabObject, string gateCondition)
    {
        Touch touch;

        if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
        {
            return;
        }

        TrackableHit     hit;
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;


        if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
        {
            // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
            // world evolves.
            var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

            // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
            // from the anchor's tracking.
            var andyObject = Instantiate(prefabObject, hit.Point, Quaternion.identity, anchor.transform);

            //***set this to true so we only do ^^^ 1 time.
            if (gateCondition == "first")
            {
                m_firstCreated = true;
            }

            if (gateCondition == "second")
            {
                m_secondCreated = true;
            }

            // Andy should look at the camera but still be flush with the plane.
            andyObject.transform.LookAt(m_firstPersonCamera.transform);
            andyObject.transform.rotation = Quaternion.Euler(0.0f,
                                                             andyObject.transform.rotation.eulerAngles.y, andyObject.transform.rotation.z);

            //set first position as these things so it can be replaced later
            if (gateCondition == "first")
            {
                //firstObjectRot = andyObject.transform.rotation;
                m_firstObjectRot = Quaternion.identity;
                m_firstObjectPos = hit.Point;
            }

            // Use a plane attachment component to maintain Andy's y-offset from the plane
            // (occurs after anchor updates).
            andyObject.GetComponent <GoogleARCore.HelloAR.PlaneAttachment> ().Attach(hit.Plane);
        }
    }
    // Update is called once per frame
    void Update()
    {
        // Skip the update if ARCore is not tracking
        if (Frame.TrackingState != FrameTrackingState.Tracking)
        {
            return;
        }

        // Get all new planes
        List <TrackedPlane> newPlanes = new List <TrackedPlane>();

        Frame.GetNewPlanes(ref newPlanes);

        // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
        for (int i = 0; i < newPlanes.Count; i++)
        {
            // Instantiate a plane visualization prefab and set it to track the new plane.
            GameObject planeObject = Instantiate(plane, Vector3.zero, Quaternion.identity,
                                                 transform);
            planeObject.GetComponent <PlaneVisualizer>().SetPlane(newPlanes[i]);
        }

        // See if user made an touch event
        Touch touch;

        if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
        {
            return;
        }

        TrackableHit hitResult;
        // Create a raycast filter
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

        // Create a Raycast with touch position, filters and hitResult object
        if (Session.Raycast(firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hitResult))
        {
            // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
            // world evolves.
            var anchor = Session.CreateAnchor(hitResult.Point, Quaternion.identity);

            // Intanstiate a Deadpool object as a child of the anchor;
            // It's transform will now benefit from the anchor's tracking.
            var newcat = Instantiate(catobj, hitResult.Point, Quaternion.identity,
                                     anchor.transform);

            // Make the model look at the camera
            newcat.transform.LookAt(firstPersonCamera.transform);
            newcat.transform.rotation = Quaternion.Euler(0.0f,
                                                         newcat.transform.rotation.eulerAngles.y, newcat.transform.rotation.z);
        }
    }
Exemple #8
0
        private void PlaceElement(Touch touch)
        {
            TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

            TrackableHit hit;

            if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
            {
                // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                // world evolves.
                _anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                GameObject parentTile = Instantiate(parentCubePrefab, hit.Point, Quaternion.identity, _anchor.transform);
                tilesArray = new GameObject[levelSizeX, levelSizeZ];

                // Intanstiate an tile objects as a child of the anchor; it's transform will now benefit
                // from the anchor's tracking.
                for (int i = 0; i < levelSizeX; i++)
                {
                    for (int j = 0; j < levelSizeZ; j++)
                    {
                        if (boardItemsArray[i, j] != 2)
                        {
                            Vector3    tilePos = hit.Point + new Vector3(0 + i * 0.104f, 0f, 0 + j * 0.104f);
                            GameObject tile    = Instantiate(tilePrefab, tilePos, Quaternion.identity, parentTile.transform);
                            tile.transform.parent = parentTile.transform;
                            tiles.Add(tile);
                            tilesArray[i, j] = tile;
                        }
                    }
                }
                parentTile.transform.LookAt(m_firstPersonCamera.transform);
                parentTile.transform.rotation = Quaternion.Euler(0.0f, parentTile.transform.rotation.eulerAngles.y + 180, parentTile.transform.rotation.z);
                spawnerScript.SpawnAll(boardItemsArray, tilesArray, m_firstPersonCamera, _anchor);

                // Place the UI buttons in worldspace
                ButtonBar.transform.parent = parentTile.transform; // Anchor the world space UI buttons
                var left   = tilesArray[0, tilesArray.GetLength(1) / 2].transform.position;
                var top    = tilesArray[tilesArray.GetLength(0) / 2, tilesArray.GetLength(1) - 1].transform.position;
                var right  = tilesArray[tilesArray.GetLength(0) - 1, tilesArray.GetLength(1) / 2].transform.position;
                var bottom = tilesArray[tilesArray.GetLength(0) / 2, 0].transform.position;
                DirectionButtons[0].transform.position = top + new Vector3(0, 0.001f, 0.3f);
                DirectionButtons[1].transform.position = right + new Vector3(0.3f, 0.001f, 0);
                DirectionButtons[2].transform.position = bottom + new Vector3(0, 0.001f, -0.3f);
                DirectionButtons[3].transform.position = left + new Vector3(-0.3f, 0.001f, 0);
                for (int i = 0; i < DirectionButtons.Length; i++)
                {
                    DirectionButtons[i].transform.rotation = Quaternion.Euler(90.0f, parentTile.transform.rotation.eulerAngles.y, parentTile.transform.rotation.z);
                }
            }
        }
        /// <summary>
        /// Hit test against all detected planes. If point cloud hit flag is enabled, it will return point
        /// cloud hit if there's no plane hit found.
        /// </summary>
        /// <param name="screenUV">Touch UV point in Unity screen space.
        ///     The bottom-left of the screen is (0,0); the right-top is (pixelWidth,pixelHeight).</param>
        /// <param name="hitTestType">Hit test method used.</param>
        /// <param name="hitPose">Output pose if hit test is successful.</param>
        /// <returns>Return true if hit test is successful, otherwise false.</returns>
        public bool Raycast(Ray ray, TrackableHitFlag filter, out TrackableHit hitResult)
        {
            TrackableHit?closestHit = null;

            Frame.GetAllPlanes(ref m_allPlanes);

            for (int i = 0; i < m_allPlanes.Count; i++)
            {
                TrackableHit?currentHit = null;

                if (!m_allPlanes[i].IsValid || m_allPlanes[i].SubsumedBy != null)
                {
                    continue;
                }

                TrackableHit hit;
                if (HitTestPlane(ray, filter, m_allPlanes[i], out hit))
                {
                    currentHit = hit;
                }

                if (currentHit != null && (closestHit == null || Vector3.Distance(ray.origin, currentHit.Value.Point)
                                           < Vector3.Distance(ray.origin, closestHit.Value.Point)))
                {
                    closestHit = currentHit;
                }
            }

            if (closestHit != null)
            {
                hitResult = closestHit.Value;
                return(true);
            }
            else
            {
                if (_HasFlag(filter, TrackableHitFlag.PointCloud))
                {
                    Vector3 hitpoint = new Vector3();
                    if (_IsRayIntersectingPoint(ray, Frame.PointCloud, ref hitpoint))
                    {
                        hitResult = new TrackableHit(hitpoint, Vector3.up, Vector3.Distance(hitpoint, ray.origin),
                                                     TrackableHitFlag.PointCloud, null);
                        return(true);
                    }
                }
            }

            hitResult = new TrackableHit(Vector3.zero, Vector3.zero, 0.0f, 0, null);
            return(false);
        }
Exemple #10
0
    // Update is called once per frame
    void Update()
    {
        if (snakeInstance == null || snakeInstance.activeSelf == false)
        {
            pointer.SetActive(false);
            return;
        }
        else
        {
            pointer.SetActive(true);
        }

        // Raycast the center of the screen as the gaze point.
        Ray ray = firstPersonCamera.ScreenPointToRay(new Vector2(Screen.width / 2, Screen.height / 2));

        TrackableHit     hit;
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds;

        // If it hits an ARCore plane, move the pointer to that location.
        if (Session.Raycast(ray, raycastFilter, out hit))
        {
            Vector3 pt = hit.Point;
            //Set the Y to the Y of the snakeInstance
            pt.y = snakeInstance.transform.position.y;
            // Set the y position relative to the plane and attach the pointer to the plane
            Vector3 pos = pointer.transform.position;
            pos.y = pt.y;
            pointer.transform.position = pos;

            // Now lerp to the position
            pointer.transform.position = Vector3.Lerp(pointer.transform.position, pt,
                                                      Time.smoothDeltaTime * speed);
        }

        // Move towards the pointer, slow down if very close.
        float dist = Vector3.Distance(pointer.transform.position,
                                      snakeInstance.transform.position) - 0.05f;

        if (dist < 0)
        {
            dist = 0;
        }

        Rigidbody rb = snakeInstance.GetComponent <Rigidbody>();

        rb.transform.LookAt(pointer.transform.position);
        rb.velocity = snakeInstance.transform.localScale.x *
                      snakeInstance.transform.forward * dist / .01f;
    }
    // add a point to the road path
    public void AddPoint(Vector3 pointPosition)
    {
        // find the point on the detected planes where the point should be placed
        TrackableHit     hit;
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;
        Ray ray = new Ray(arCamera.transform.position, pointPosition - arCamera.transform.position);

        if (Session.Raycast(ray, raycastFilter, out hit))
        {
            // add point to collection
            pathPoints.Add(new Vector2(pointPosition.x, pointPosition.z));
            // select the right prefab for the marker
            GameObject marker;
            if (pathMarkers.Count == 0)
            {
                marker = firstPointPrefab;
            }
            else
            {
                marker = pointPrefab;
            }

            // create an anchor to allow ARCore to track the hitpoint as understanding of the physical world evolves
            var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

            // Intanstiate the object as a child of the anchor; it's transform will now benefit from the anchor's tracking
            GameObject newMarker = Instantiate(marker, hit.Point, Quaternion.identity, anchor.transform);
            pathMarkers.Add(newMarker);

            // play animations on the markers
            if (pathMarkers.Count == 1)
            {
                Animation anim = pathMarkers[0].GetComponent <Animation>();
                if (anim)
                {
                    anim.Play("animIn");
                    anim.PlayQueued("idle", QueueMode.CompleteOthers);
                }
            }
            // place the undo button
            if (currentUndoButton)
            {
                Destroy(currentUndoButton);
            }
            currentUndoButton = Instantiate(undoButtonPrefab, hit.Point + Vector3.up * 0.03f, Quaternion.identity);
            // update the path line
            UpdateLineRenderer();
        }
    }
Exemple #12
0
    /// <summary>
    /// The Unity Update() method.
    /// </summary>
    ///

    public void Update()
    {
        _QuitOnConnectionErrors();

        // The tracking state must be FrameTrackingState.Tracking in order to access the Frame.
        if (Frame.TrackingState != FrameTrackingState.Tracking)
        {
            const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
            Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
            return;
        }

        Screen.sleepTimeout = SleepTimeout.NeverSleep;
        Frame.GetNewPlanes(ref m_newPlanes);

        // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
        for (int i = 0; i < m_newPlanes.Count; i++)
        {
            // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
            // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
            // coordinates.
            GameObject planeObject = Instantiate(m_trackedPlanePrefab, Vector3.zero, Quaternion.identity,
                                                 transform);
            planeObject.GetComponent <CatPlaneVisualizer>().SetTrackedPlane(m_newPlanes[i]);

            // Apply a random grid rotation.
            planeObject.GetComponent <Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
        }

        if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
        {
            return;
        }

        TrackableHit     hit;
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

        if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
        {
            var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

            var catObject = Instantiate(kittenPrefab, hit.Point, Quaternion.identity, anchor.transform);

            catObject.transform.LookAt(m_firstPersonCamera.transform);
            catObject.transform.rotation = Quaternion.Euler(0.0f, catObject.transform.rotation.eulerAngles.y, catObject.transform.rotation.z);

            catObject.GetComponent <PlaneAttachment>().Attach(hit.Plane);
        }
    }
Exemple #13
0
        private void PlaceFireTouch(Touch touch)
        {
            TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

            TrackableHit hit;

            if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
            {
                // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                // world evolves.
                var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
                // from the anchor's tracking.
                Instantiate(fireTouch, hit.Point + new Vector3(0, 0, 0), Quaternion.identity, anchor.transform);
            }
        }
 public void LateUpdate()
 {
     // update the reticle's position on the ground
     if (state == State.Placing || state == State.Calibrating)
     {
         TrackableHit     hit;
         TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;
         Ray ray = new Ray(arCamera.transform.position, arCamera.transform.forward);
         if (Session.Raycast(ray, raycastFilter, out hit))
         {
             // cast a ray to the middle of the screen and place the reticle there
             reticle.transform.position = hit.Point;
             float tangoYaw = arCamera.transform.rotation.eulerAngles.y;
             reticle.transform.rotation = Quaternion.Euler(0, tangoYaw, 0);
         }
     }
 }
Exemple #15
0
    /// <summary>
    /// Processes a single tap to select a plane based on a hittest.
    /// </summary>
    private void ProcessTouches()
    {
        Touch touch;

        if (Input.touchCount != 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
        {
            return;
        }

        TrackableHit     hit;
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

        if (Session.Raycast(firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
        {
            SetSelectedPlane(hit.Plane);
        }
    }
Exemple #16
0
        protected override void MoveTouch(Vector3 pos)
        {
            TrackableHit     hit;
            TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinPolygon;

            //| TrackableHitFlag.PlaneWithinInfinity;

            if (Session.Raycast(Camera.main.ScreenPointToRay(pos), raycastFilter, out hit))
            {
                Debug.Log("Hit: " + hit.Point);

                // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                // world evolves.
                var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                controller.transform.position = hit.Point;
                controller.transform.parent   = anchor.transform;
                Attach(hit.Plane);
            }
        }
Exemple #17
0
    void AnchorCatPlacement()
    {
        // See if user made an touch event
        Touch touch;

        if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
        {
            return;
        }

        TrackableHit hitResult;
        // Create a raycast filter
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

        // Create a Raycast with touch position, filters and hitResult object
        if (Session.Raycast(cam.ScreenPointToRay(touch.position), raycastFilter, out hitResult))
        {
            // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
            // world evolves.
            if (hitResult.Plane == areaPlanes[0])
            {
                mainAnchor       = Session.CreateAnchor(hitResult.Point, Quaternion.identity);
                CurrentGameState = playstates.InGame;
                TestingText.text = "Ready to play";
                UIManager.instance.EnableGamePlayUI();

                //change to work with new cats
                cats[0].gameObject.SetActive(true);
                cats[0].transform.position = hitResult.Point;
                cats[0].transform.parent   = mainAnchor.transform;
                cats[0].transform.rotation = Quaternion.identity;
                mainCat = cats[0].gameObject;
                UIManager.instance.setAttributes();
                UIManager.instance.StartTimer();
            }
        }
    }
    private void OnTouch(Vector2 touch)
    {
        TrackableHit     hit;
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

        if (Session.Raycast(firstPersonCamera.ScreenPointToRay(touch), raycastFilter, out hit))
        {
            if (akira == null)
            {
                SpawnCharacter(hit);
            }
            else
            {
                akira.WalkToPosition(hit.Point);
            }
        }
        else
        {
            if (akira != null)
            {
                akira.TriggerExcited();
            }
        }
    }
        public bool HitTestPlane(Ray ray, TrackableHitFlag hitFilterFlags, TrackedPlane plane, out TrackableHit hit)
        {
            Plane unityPlane = new Plane(plane.Rotation * Vector3.up, plane.Position);
            float distance;

            if (unityPlane.Raycast(ray, out distance))
            {
                Vector3          hitPoint       = ray.GetPoint(distance);
                TrackableHitFlag hitResultFlags = TrackableHitFlag.None;

                if (_HasFlag(hitFilterFlags, TrackableHitFlag.PlaneWithinBounds) &&
                    _IsPointInBoundingBox(hitPoint, plane))
                {
                    hitResultFlags = hitResultFlags | TrackableHitFlag.PlaneWithinBounds;
                }

                if (_HasFlag(hitFilterFlags, TrackableHitFlag.PlaneWithinPolygon) && _IsPointInPolygon(hitPoint, plane))
                {
                    hitResultFlags |= TrackableHitFlag.PlaneWithinPolygon;
                }

                if (_HasFlag(hitFilterFlags, TrackableHitFlag.PlaneWithinInfinity))
                {
                    hitResultFlags |= TrackableHitFlag.PlaneWithinInfinity;
                }

                if (hitResultFlags != TrackableHitFlag.None)
                {
                    hit = new TrackableHit(hitPoint, unityPlane.normal, distance, hitResultFlags, plane);
                    return(true);
                }
            }

            hit = new TrackableHit(Vector3.zero, Vector3.zero, 0.0f, 0, null);
            return(false);
        }
Exemple #20
0
 /// <summary>
 /// Performs a raycast against physical objects being tracked by ARCore.
 /// </summary>
 /// <param name="ray">The starting point and direction of the ray.</param>
 /// <param name="filter">A filter bitmask where each <c>TrackableHitFlag</c> which is set represents a category
 /// of raycast hits the method call should consider valid.</param>
 /// <param name="hitResult">A <c>TrackableHit</c> that will be set if the raycast is successful.</param>
 /// <returns><c>true</c> if the raycast had a hit, otherwise <c>false</c>.</returns>
 public static bool Raycast(Ray ray, TrackableHitFlag filter, out TrackableHit hitResult)
 {
     return(SessionManager.Instance.RaycastManager.Raycast(ray, filter, out hitResult));
 }
    /// <summary>
    /// The Unity Update() method.
    /// </summary>
    void Update()
    {
        bool hasTouch = Input.touchCount > 0;

        if (hasTouch)
        {
            // Ignore touches on buttons
            bool isTouch0OverButton = EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId);
            hasTouch = !isTouch0OverButton;
        }

        bool didFindSurface = false;

        if (m_selectedAirspace == null)
        {
            m_placementShadow.SetActive(false);
        }
        else
        {
            if (!hasTouch && !m_selectedAirspace.activeInHierarchy)
            {
                TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds |
                                                 TrackableHitFlag.PlaneWithinPolygon;
                TrackableHit hit;
                Vector2      center = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
                didFindSurface = Session.Raycast(m_firstPersonCamera.ScreenPointToRay(center), raycastFilter, out hit);

                if (didFindSurface)
                {
                    m_placementTargetPos = hit.Point;
                    if (!m_placementShadow.activeInHierarchy)
                    {
                        m_placementShadow.SetActive(true);
                        m_placementShadow.transform.position = m_placementTargetPos;
                    }
                }
            }
            else
            {
                // Hide when touch is down
                m_placementShadow.SetActive(false);
            }
        }

        if (hasTouch && m_selectedAirspace != null)
        {
            Touch touch = Input.GetTouch(0);
            if (touch.phase == TouchPhase.Began)
            {
                if (m_selectedAirspace.activeInHierarchy)
                {
                    m_selectedAirspace.SetActive(false);
                }
                else
                {
                    // Only place where we've presented a surface
                    m_selectedAirspace.transform.position = m_placementShadow.transform.position;
                    m_selectedAirspace.GetComponent <SplineReader>().Reset();
                    m_selectedAirspace.SetActive(true);
                    m_placementShadow.SetActive(false);
                }
            }
        }

        bool areSplinesVisible = m_selectedAirspace != null && m_selectedAirspace.activeInHierarchy;

                #if UNITY_EDITOR
        areSplinesVisible = true;
                #endif
        m_skyboxDim.SetActive(areSplinesVisible);
        if (areSplinesVisible)
        {
            RenderSettings.fog = true;
            m_lookingImage.gameObject.SetActive(false);
        }
        else
        {
            RenderSettings.fog = false;
            List <TrackedPlane> planes = new List <TrackedPlane>();
            Frame.GetAllPlanes(ref planes);
            if (planes.Count > 0)
            {
                m_lookingImage.gameObject.SetActive(false);
            }
            else
            {
                m_lookingImage.gameObject.SetActive(true);
            }
        }
    }
Exemple #22
0
    /// <summary>
    /// The Unity Update() method.
    /// </summary>
    public void Update()
    {
        _QuitOnConnectionErrors();

        // The tracking state must be FrameTrackingState.Tracking in order to access the Frame.
        if (Frame.TrackingState != FrameTrackingState.Tracking)
        {
            const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
            Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
            return;
        }

        Screen.sleepTimeout = SleepTimeout.NeverSleep;
        Frame.GetNewPlanes(ref m_newPlanes);

        // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
        for (int i = 0; i < m_newPlanes.Count; i++)
        {
            // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
            // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
            // coordinates.
            GameObject planeObject = Instantiate(m_trackedPlanePrefab, Vector3.zero, Quaternion.identity,
                                                 transform);
            planeObject.GetComponent <TrackedPlaneVisualizer>().SetTrackedPlane(m_newPlanes[i]);

            // Apply a random color and grid rotation.
            planeObject.GetComponent <Renderer>().material.SetColor("_GridColor", m_planeColors[Random.Range(0,
                                                                                                             m_planeColors.Length - 1)]);
            planeObject.GetComponent <Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
        }

        // Disable the snackbar UI when no planes are valid.
        bool showSearchingUI = true;

        Frame.GetAllPlanes(ref m_allPlanes);
        for (int i = 0; i < m_allPlanes.Count; i++)
        {
            if (m_allPlanes[i].IsValid)
            {
                showSearchingUI = false;
                break;
            }
        }

        m_searchingForPlaneUI.SetActive(showSearchingUI);
        Touch touch;

        if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
        {
            return;
        }

        TrackableHit     hit;
        TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

        if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit) && !UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
        {
            // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
            // world evolves.
            var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

            //Set the drone active.
            drone.SetActive(true);
            //Position the solar system at the hit point
            drone.transform.position = hit.Point;


            // The drone should look at the camera but still be flush with the plane.
            drone.transform.LookAt(m_firstPersonCamera.transform);
            drone.transform.rotation = Quaternion.Euler(0.0f,
                                                        drone.transform.rotation.eulerAngles.y, drone.transform.rotation.z);

            // Use a plane attachment component to maintain the Drone's y-offset from the plane
            // (occurs after anchor updates).
            drone.GetComponent <PlaneAttachment>().Attach(hit.Plane);
        }
    }
Exemple #23
0
        /// <summary>
        /// The Unity Update() method.
        /// </summary>
        public void Update()
        {
            _QuitOnConnectionErrors();

            // The tracking state must be FrameTrackingState.Tracking in order to access the Frame.
            if (Frame.TrackingState != FrameTrackingState.Tracking)
            {
                const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
                Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
                return;
            }

            Screen.sleepTimeout = SleepTimeout.NeverSleep;
            if (mainSpawn < 1)
            {
                Frame.GetNewPlanes(ref m_newPlanes);
            }
            //info.text = mainSpawn.ToString();
            // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
            for (int i = 0; i < m_newPlanes.Count; i++)
            {
                // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
                // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
                // coordinates.
                if (mainSpawn >= 1)
                {
                    break;
                }
                else
                {
                    mainSpawn += 1;
                    GameObject planeObject = Instantiate(m_trackedPlanePrefab, Vector3.zero, Quaternion.identity,
                                                         transform);
                    planeObject.GetComponent <TrackedPlaneVisualizer>().SetTrackedPlane(m_newPlanes[i]);

                    // Apply a random color and grid rotation.
                    planeObject.GetComponent <Renderer>().material.SetColor("_GridColor", new Color(0f, 0.588f, 0.533f));
                    planeObject.GetComponent <Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
                }
            }
            // Disable the snackbar UI when no planes are valid.
            bool showSearchingUI = true;

            Frame.GetAllPlanes(ref m_allPlanes);
            for (int i = 0; i < m_allPlanes.Count; i++)
            {
                if (m_allPlanes[i].IsValid)
                {
                    showSearchingUI = false;
                    break;
                }
            }
            if (m_allPlanes.Count > 0 && fencespawn < 1)
            {
                fencespawn++;
                fence = (GameObject)Resources.Load("Fence");
                var     plane  = m_allPlanes[0];
                Vector3 center = plane.Position;
                float   x      = plane.Bounds.x;
                float   z      = plane.Bounds.y;
                fencex = x;
                fencez = z;
                var anchor = Session.CreateAnchor(center, Quaternion.identity);
                if (x <= z)
                {
                    x /= 1.5f;
                    var scale = fence.transform.localScale;
                    scale.x = x;
                    scale.z = x;
                    scale.y = x;
                    fence.transform.localScale = scale;
                }
                else
                {
                    z /= 1.5f;
                    fence.transform.localScale = new Vector3(z, z, z);
                }
                var andyObject = Instantiate(fence, center, Quaternion.identity,
                                             anchor.transform);
                andyObject.transform.LookAt(m_firstPersonCamera.transform);
                andyObject.transform.rotation = Quaternion.Euler(0.0f,
                                                                 andyObject.transform.rotation.eulerAngles.y, andyObject.transform.rotation.z);

                // Use a plane attachment component to maintain Andy's y-offset from the plane
                // (occurs after anchor updates).
                andyObject.GetComponent <PlaneAttachment>().Attach(plane);
                fence = andyObject;
            }
            if (fence != null)
            {
                resizeFence();
                groundtrees();
            }
            //m_searchingForPlaneUI.SetActive(showSearchingUI);
            if (Input.touchCount < 1)
            {
                // info.text = "not touched";
                return;
            }
            Touch touch;

            touch = Input.GetTouch(0);
            RaycastHit hits;
            Ray        ray = m_firstPersonCamera.ScreenPointToRay(touch.position);

            if (Physics.Raycast(ray, out hits, 500))
            {
                string i = hits.transform.tag;
                //info.text = hits.transform.tag;
                if (i == "Box")
                {
                    //currentSpawn.text = hits.transform.name;

                    Toclone = (GameObject)Resources.Load(hits.transform.name);
                    return;
                }
            }

            TrackableHit     hit;
            TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

            if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit) && Toclone != null)
            {
                if (touch.phase.Equals(TouchPhase.Began))
                {
                    if (GameObject.FindGameObjectsWithTag("Character").Length > 0 && Toclone.transform.tag.Equals("Character"))
                    {
                        return;
                    }
                    if (Physics.Raycast(ray, out hits, 500))
                    {
                        if (hits.transform.tag.Equals("Interactable"))
                        {
                            focus = hits.transform.gameObject;
                            return;
                        }
                    }
                    // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                    // world evolves.
                    var set    = hit.Point;
                    var anchor = Session.CreateAnchor(set, Quaternion.identity);

                    // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
                    // from the anchor's tracking.
                    if (Toclone.transform.name.Equals("River") && m_allPlanes.Count > 0)
                    {
                        var     plane  = m_allPlanes[0];
                        float   x      = plane.Bounds.x;
                        Vector3 center = plane.Position;
                        set.x = center.x;
                        var scale = Toclone.transform.localScale;
                        scale.x = x;
                        Toclone.transform.localScale = scale;
                    }
                    if (Toclone.transform.name.StartsWith("tre"))
                    {
                        int    trenmbr   = Random.Range(1, 11);
                        string clonename = "tree00" + trenmbr.ToString();
                        //currentSpawn.text = clonename;
                        Toclone = (GameObject)Resources.Load(clonename);
                        var scale = Toclone.transform.localScale;
                        scale = new Vector3(0.04f, 0.04f, 0.04f);
                        Toclone.transform.localScale = scale;
                    }
                    if (Toclone.transform.name.Equals("Fence") && m_allPlanes.Count > 0)
                    {
                        var     plane  = m_allPlanes[0];
                        Vector3 center = plane.Position;
                        set.x = center.x;
                        set.z = center.z;
                        float x = plane.Bounds.x;
                        float z = plane.Bounds.y;
                        if (x <= z)
                        {
                            x /= 1.5f;
                            var scale = Toclone.transform.localScale;
                            scale.x = x;
                            scale.z = x;
                            scale.y = x;
                            Toclone.transform.localScale = scale;
                            //currentSpawn.text = x.ToString();
                        }
                        else
                        {
                            z /= 1.5f;
                            Toclone.transform.localScale = new Vector3(z, z, z);
                            //currentSpawn.text = (x/2).ToString();
                        }
                    }

                    /*
                     *------------------------------------------------------
                     * ----------------SPAWNING-----------------------------
                     * -----------------------------------------------------
                     */
                    var andyObject = Instantiate(Toclone, set, Quaternion.identity,
                                                 fence.transform);
                    SendItemToMulitplayer(Toclone, set.x, set.y, set.z);
                    if (Toclone.transform.tag.Equals("Character"))
                    {
                        mainSpawn++;
                    }

                    // Andy should look at the camera but still be flush with the plane.
                    andyObject.transform.LookAt(m_firstPersonCamera.transform);
                    andyObject.transform.rotation = Quaternion.Euler(0.0f,
                                                                     andyObject.transform.rotation.eulerAngles.y, andyObject.transform.rotation.z);

                    // Use a plane attachment component to maintain Andy's y-offset from the plane
                    // (occurs after anchor updates).
                    andyObject.GetComponent <PlaneAttachment>().Attach(hit.Plane);
                }
                if (touch.phase.Equals(TouchPhase.Moved) && focus != null)
                {
                    focus.transform.position = hit.Point;
                }
                if (touch.phase.Equals(TouchPhase.Ended) && focus != null)
                {
                    focus = null;
                }
            }
        }
        /// <summary>
        /// The Unity Update() method.
        /// </summary>
        public void Update()
        {
            _QuitOnConnectionErrors();

            // Update the positions of the characters roughly every second
            count++;
            if (count > 100 && setup)
            {
                count = 0;
                StartCoroutine(GetUpdatedCharacters());
            }

            // The tracking state must be FrameTrackingState.Tracking in order to access the Frame.
            if (Frame.TrackingState != FrameTrackingState.Tracking)
            {
                const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
                Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
                return;
            }

            Screen.sleepTimeout = SleepTimeout.NeverSleep;
            Frame.GetNewPlanes(ref m_newPlanes);

            // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
            for (int i = 0; i < m_newPlanes.Count; i++)
            {
                // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
                // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
                // coordinates.
                GameObject planeObject = Instantiate(m_trackedPlanePrefab, Vector3.zero, Quaternion.identity,
                                                     transform);
                planeObject.GetComponent <TrackedPlaneVisualizer>().SetTrackedPlane(m_newPlanes[i]);

                // Apply a random color and grid rotation.
                planeObject.GetComponent <Renderer>().material.SetColor("_GridColor", m_planeColors[Random.Range(0,
                                                                                                                 m_planeColors.Length - 1)]);
                planeObject.GetComponent <Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
            }

            // Disable the snackbar UI when no planes are valid.
            bool showSearchingUI = true;

            Frame.GetAllPlanes(ref m_allPlanes);
            for (int i = 0; i < m_allPlanes.Count; i++)
            {
                if (m_allPlanes[i].IsValid)
                {
                    showSearchingUI = false;
                    break;
                }
            }

            m_searchingForPlaneUI.SetActive(showSearchingUI);

            Touch touch = Input.GetTouch(0);

            if (Input.touchCount < 1 || touch.phase != TouchPhase.Began)
            {
                return;
            }

            RaycastHit arHit;

            TrackableHit     hit;
            TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

            Ray ray = m_firstPersonCamera.ScreenPointToRay(touch.position);

            //If the click by the user landed on an existing object
            if (Physics.Raycast(ray, out arHit, Mathf.Infinity))
            {
                GameObject hitObject     = arHit.collider.gameObject;
                int        hitX          = hitObject.GetComponent <TileRunner>().x;
                int        hitZ          = hitObject.GetComponent <TileRunner>().z;
                bool       alreadyMoving = false;
                int        existingX     = -1;
                int        existingZ     = -1;

                //Determine if we we're already trying to move from somewhere
                for (int i = 0; i < cells.GetLength(0); i++)
                {
                    for (int j = 0; j < cells.GetLength(1); j++)
                    {
                        if (cells[i, j].GetComponent <TileRunner>().isSelected == true)
                        {
                            alreadyMoving = true;
                            existingX     = i;
                            existingZ     = j;
                            break;
                        }
                    }
                    if (alreadyMoving)
                    {
                        break;
                    }
                }

                //There was already a selected tile, so move that character to here.
                if (alreadyMoving)
                {
                    bool legalMove = false;
                    //Make sure that the point they're trying to go to is within their range.
                    for (int x = 0; x < coordSets.Count; x++)
                    {
                        for (int z = 0; z < coordSets[x].Count; z++)
                        {
                            if (coordSets[x][z].First == hitX && coordSets[x][z].Second == hitZ)
                            {
                                legalMove = true;
                            }
                        }
                    }
                    if (legalMove)
                    {
                        //Look for the character from the old point
                        GameObject character = null;
                        for (int i = 0; i < characters.Count; i++)
                        {
                            if (characters[i].GetComponent <CharacterRunner>().x == existingX && characters[i].GetComponent <CharacterRunner>().z == existingZ)
                            {
                                character = characters[i];
                                break;
                            }
                        }
                        //We found the character that needs to be moved, so move it
                        if (character != null)
                        {
                            StartCoroutine(ClearPaths());
                            character.GetComponent <CharacterRunner>().x = hitX;
                            character.GetComponent <CharacterRunner>().z = hitZ;
                            StartCoroutine(PostUpdatedCharacters(character));
                            character.GetComponent <CharacterRunner>().moving = false;
                            cells[existingX, existingZ].GetComponent <TileRunner>().selected(false);
                        }
                    }
                }
                //A tile hasn't already been selected, select this one to move from
                else
                {
                    //Check to make sure a character is on the spot that was selected
                    bool       charExists = false;
                    GameObject character  = null;
                    for (int i = 0; i < characters.Count; i++)
                    {
                        if (characters[i].GetComponent <CharacterRunner>().x == hitX && characters[i].GetComponent <CharacterRunner>().z == hitZ)
                        {
                            charExists = true;
                            break;
                        }
                    }
                    //Save the details about the potential move to show the path lines
                    if (charExists)
                    {
                        fromX = hitX;
                        fromZ = hitZ;

                        coordSets = new List <List <Tuple <int, int> > >();

                        if (character != null)
                        {
                            movingChar = character;
                            character.GetComponent <CharacterRunner>().moving = true;
                        }
                        hitObject.GetComponent <TileRunner>().selected(true);

                        //Start calculating the character's path options
                        StartCoroutine(ShowPaths());
                    }
                }
            }
            //The users's click landed on the ARField behind the objects
            else if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
            {
                //Only go through the setup on the first tap on ARField
                if (!setup)
                {
                    setup = true;

                    // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                    // world evolves.
                    var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                    cells = new GameObject[sizeX, sizeZ];

                    for (int x = 0; x < sizeX; x++)
                    {
                        for (int z = 0; z < sizeZ; z++)
                        {
                            CreateCell(x, z, hit.Point, anchor.transform, hit);
                        }
                    }

                    StartCoroutine(GetCampaign("59c6e98c945f7c44deb85b48"));
                }
                //The BattleMat already exists, user is just trying to move it
                else
                {
                    var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);
                    for (int x = 0; x < sizeX; x++)
                    {
                        for (int z = 0; z < sizeZ; z++)
                        {
                            UpdateCell(x, z, hit.Point, anchor.transform, hit);
                        }
                    }
                }
            }

            //Update the walls to follow the floors
            for (int i = 0; i < wallIds.Count; i++)
            {
                //Get the data about the walls
                float startX = (float)wallIds[i].GetComponent <WallRunner>().startX;
                float startZ = (float)wallIds[i].GetComponent <WallRunner>().startZ;
                float endX   = (float)wallIds[i].GetComponent <WallRunner>().endX;
                float endZ   = (float)wallIds[i].GetComponent <WallRunner>().endZ;

                //Plan where to place the walls
                float   diffX = (endX - startX) * 0.05f;
                float   diffZ = (endZ - startZ) * 0.05f;
                Vector3 pos   = cells[(int)startX, (int)startZ].transform.position;
                pos = pos + new Vector3(diffX, 0.075f, diffZ);

                wallIds[i].GetComponent <Transform>().position = pos;
            }
        }
        /// <summary>
        /// The Unity Update() method.
        /// </summary>
        public void Update()
        {
            _QuitOnConnectionErrors();

            // The tracking state must be FrameTrackingState.Tracking in order to access the Frame.
            if (Frame.TrackingState != FrameTrackingState.Tracking)
            {
                const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
                Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
                return;
            }

            Screen.sleepTimeout = SleepTimeout.NeverSleep;
            Frame.GetNewPlanes(ref m_newPlanes);

            // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
            for (int i = 0; i < m_newPlanes.Count; i++)
            {
                // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
                // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
                // coordinates.
                GameObject planeObject = Instantiate(m_trackedPlanePrefab, Vector3.zero, Quaternion.identity,
                                                     transform);
                planeObject.GetComponent <TrackedPlaneVisualizer>().SetTrackedPlane(m_newPlanes[i]);

                // Apply a random color and grid rotation.
                planeObject.GetComponent <Renderer>().material.SetColor("_GridColor", m_planeColors[Random.Range(0,
                                                                                                                 m_planeColors.Length - 1)]);
                planeObject.GetComponent <Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
            }

            // Disable the snackbar UI when no planes are valid.
            bool showSearchingUI = true;

            Frame.GetAllPlanes(ref m_allPlanes);
            for (int i = 0; i < m_allPlanes.Count; i++)
            {
                if (m_allPlanes[i].IsValid)
                {
                    showSearchingUI = false;
                    break;
                }
            }

            m_searchingForPlaneUI.SetActive(showSearchingUI);

            if (Input.GetKeyDown(KeyCode.Escape))
            {
                _isSpawned = false;
            }

            Touch touch;

            if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
            {
                return;
            }

            if (!_isSpawned)
            {
                TrackableHit     hit;
                TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

                if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
                {
                    // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                    // world evolves.
                    var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                    // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
                    // from the anchor's tracking.
                    var containerInstance = Instantiate(m_containerPrefab, hit.Point, Quaternion.identity, anchor.transform);

                    // Andy should look at the camera but still be flush with the plane.
                    containerInstance.transform.LookAt(m_firstPersonCamera.transform);
                    containerInstance.transform.rotation = Quaternion.Euler(0.0f, containerInstance.transform.rotation.eulerAngles.y, containerInstance.transform.rotation.z);

                    // Use a plane attachment component to maintain Andy's y-offset from the plane
                    // (occurs after anchor updates).
                    containerInstance.GetComponent <PlaneAttachment>().Attach(hit.Plane);

                    _videoPlayer = containerInstance.GetComponentInChildren <VideoPlayer>();

                    _isSpawned = true;
                }
            }
            else
            {
                if (_videoPlayer.isPlaying)
                {
                    Application.OpenURL("https://www.saechsische-schweiz.de");
                }
                else
                {
                    _videoPlayer.Play();
                }
            }
        }
 private bool _HasFlag(TrackableHitFlag filter, TrackableHitFlag flag)
 {
     return((filter & flag) != TrackableHitFlag.None);
 }
Exemple #27
0
        public void Update()
        {
            _QuitOnConnectionErrors();

            // The tracking state must be FrameTrackingState.Tracking in order to access the Frame.
            if (Frame.TrackingState != FrameTrackingState.Tracking)
            {
                const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
                Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
                return;
            }

            Screen.sleepTimeout = SleepTimeout.NeverSleep;
            Frame.GetNewPlanes(ref m_newPlanes);

            // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
            for (int i = 0; i < m_newPlanes.Count; i++)
            {
                // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
                // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
                // coordinates.
                GameObject planeObject = Instantiate(m_trackedPlanePrefab, Vector3.zero, Quaternion.identity,
                                                     transform);
                planeObject.GetComponent <TrackedPlaneVisualizer>().SetTrackedPlane(m_newPlanes[i]);

                // Apply a random color and grid rotation.
                planeObject.GetComponent <Renderer>().material.SetColor("_GridColor", m_planeColors[Random.Range(0,
                                                                                                                 m_planeColors.Length - 1)]);
                planeObject.GetComponent <Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
            }

            // Disable the snackbar UI when no planes are valid.
            bool showSearchingUI = true;

            Frame.GetAllPlanes(ref m_allPlanes);
            for (int i = 0; i < m_allPlanes.Count; i++)
            {
                if (m_allPlanes[i].IsValid)
                {
                    showSearchingUI = false;
                    break;
                }
            }

            m_searchingForPlaneUI.SetActive(showSearchingUI);
            Touch touch;

            if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
            {
                return;
            }
            //if (Input.touchCount > 0)
            //{
            TrackableHit     hit;
            TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

            if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
            {
                // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                // world evolves.
                var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
                // from the anchor's tracking.
                if (!castleActive)
                {
                    var castle = Instantiate(SelectedObject, hit.Point, Quaternion.identity,
                                             anchor.transform);
                    DeleteButtonMethod();
                    ArFunctions.Instance.PutInList(castle as GameObject);

                    // Andy should look at the camera but still be flush with the plane.
                    castle.transform.LookAt(m_firstPersonCamera.transform);
                    castle.transform.rotation = Quaternion.Euler(0.0f,
                                                                 castle.transform.rotation.eulerAngles.y, castle.transform.rotation.z);

                    // Use a plane attachment component to maintain Andy's y-offset from the plane
                    // (occurs after anchor updates).
                    castle.GetComponent <PlaneAttachment>().Attach(hit.Plane);
                    castleActive = true;
                }
                else
                {
                    CheckForCollision();
                    return;
                }



                //if (Input.GetTouch(0).phase == touchPhase)
                //{
                //    Ray worldRay = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);

                //    if (hitInfo.collider != null)
                //    {
                //        if (detectedObject != null)
                //        {
                //            previousObject = detectedObject;
                //        }
                //        detectedObject = hitInfo.collider.gameObject;

                //        if (detectedObject.name == "Delete")
                //        {
                //            andyObject.SetActive(false);
                //        }

                //        string temp = detectedObject.name;

                //    }
                //}
                //}
            }
        }
Exemple #28
0
        public void Update()
        {
            _QuitOnConnectionErrors();


            if (Frame.TrackingState != FrameTrackingState.Tracking)
            {
                const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
                Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
                return;
            }

            Screen.sleepTimeout = SleepTimeout.NeverSleep;
            Frame.GetNewPlanes(ref m_newPlanes);


            for (int i = 0; i < m_newPlanes.Count; i++)
            {
                GameObject planeObject = Instantiate(m_trackedPlanePrefab, Vector3.zero, Quaternion.identity,
                                                     transform);
                planeObject.GetComponent <TrackedPlaneVisualizer>().SetTrackedPlane(m_newPlanes[i]);

                planeObject.GetComponent <Renderer>().material.SetColor("_GridColor", m_planeColors[Random.Range(0,
                                                                                                                 m_planeColors.Length - 1)]);
                planeObject.GetComponent <Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
            }


            bool showSearchingUI = true;

            Frame.GetAllPlanes(ref m_allPlanes);
            for (int i = 0; i < m_allPlanes.Count; i++)
            {
                if (m_allPlanes[i].IsValid)
                {
                    showSearchingUI = false;
                    break;
                }
            }

            m_searchingForPlaneUI.SetActive(showSearchingUI);

            Touch touch;

            if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
            {
                return;
            }

            TrackableHit     hit;
            TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;



            if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
            {
                var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);



                if (ObjectIndex == 0)
                {
                }

                if (ObjectIndex == 1)
                {
                    var andyObject = Instantiate(m_andyAndroidPrefab, hit.Point, Quaternion.identity,
                                                 anchor.transform);
                    andyObject.tag = "markerTag";

                    andyObject.transform.LookAt(m_firstPersonCamera.transform);
                    andyObject.transform.rotation = Quaternion.Euler(0.0f,
                                                                     andyObject.transform.rotation.eulerAngles.y, andyObject.transform.rotation.z);

                    andyObject.GetComponent <PlaneAttachment>().Attach(hit.Plane);
                    ObjectIndex = 0;
                }



                if (ObjectIndex == 2)
                {
                    var andyObject2 = Instantiate(m_2andyAndroidPrefab, hit.Point, Quaternion.identity,
                                                  anchor.transform);
                    andyObject2.tag = "markerTag";

                    andyObject2.transform.LookAt(m_firstPersonCamera.transform);
                    andyObject2.transform.rotation = Quaternion.Euler(0.0f,
                                                                      andyObject2.transform.rotation.eulerAngles.y, andyObject2.transform.rotation.z);


                    andyObject2.GetComponent <PlaneAttachment>().Attach(hit.Plane);
                    ObjectIndex = 0;
                }


                if (ObjectIndex == 3)
                {
                    var andyObject3 = Instantiate(m_3andyAndroidPrefab, hit.Point, Quaternion.identity,
                                                  anchor.transform);
                    andyObject3.tag = "markerTag";

                    andyObject3.transform.LookAt(m_firstPersonCamera.transform);
                    andyObject3.transform.rotation = Quaternion.Euler(0.0f,
                                                                      andyObject3.transform.rotation.eulerAngles.y, andyObject3.transform.rotation.z);


                    andyObject3.GetComponent <PlaneAttachment>().Attach(hit.Plane);
                    ObjectIndex = 0;
                }

                if (ObjectIndex == 4)
                {
                    var andyObject4 = Instantiate(m_4andyAndroidPrefab, hit.Point, Quaternion.identity,
                                                  anchor.transform);
                    andyObject4.tag = "markerTag";

                    andyObject4.transform.LookAt(m_firstPersonCamera.transform);
                    andyObject4.transform.rotation = Quaternion.Euler(0.0f,
                                                                      andyObject4.transform.rotation.eulerAngles.y, andyObject4.transform.rotation.z);

                    andyObject4.GetComponent <PlaneAttachment>().Attach(hit.Plane);
                    ObjectIndex = 0;
                }


                if (ObjectIndex == 5)
                {
                    var andyObject5 = Instantiate(m_5andyAndroidPrefab, hit.Point, Quaternion.identity,
                                                  anchor.transform);
                    andyObject5.tag = "markerTag";

                    andyObject5.transform.LookAt(m_firstPersonCamera.transform);
                    andyObject5.transform.rotation = Quaternion.Euler(0.0f,
                                                                      andyObject5.transform.rotation.eulerAngles.y, andyObject5.transform.rotation.z);

                    andyObject5.GetComponent <PlaneAttachment>().Attach(hit.Plane);
                    ObjectIndex = 0;
                }
            }
        }
Exemple #29
0
        /// <summary>
        /// The Unity Update() method.
        /// </summary>
        ///

        public void Update()
        {
            _QuitOnConnectionErrors();

            TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

            // The tracking state must be FrameTrackingState.Tracking in order to access the Frame.
            if (Frame.TrackingState != FrameTrackingState.Tracking)
            {
                const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
                Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
                return;
            }

            Screen.sleepTimeout = SleepTimeout.NeverSleep;
            Frame.GetNewPlanes(ref m_newPlanes);

            // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
            for (int i = 0; i < m_newPlanes.Count; i++)
            {
                // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
                // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
                // coordinates.
                GameObject planeObject = Instantiate(m_trackedPlanePrefab, Vector3.zero, Quaternion.identity,
                                                     transform);
                planeObject.GetComponent <TrackedPlaneVisualizer>().SetTrackedPlane(m_newPlanes[i]);

                // Apply a random color and grid rotation.
                planeObject.GetComponent <Renderer>().material.SetColor("_GridColor", m_planeColors[Random.Range(0,
                                                                                                                 m_planeColors.Length - 1)]);
                planeObject.GetComponent <Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
            }

            // Disable the snackbar UI when no planes are valid.
            bool showSearchingUI = true;

            Frame.GetAllPlanes(ref m_allPlanes);
            for (int i = 0; i < m_allPlanes.Count; i++)
            {
                if (m_allPlanes[i].IsValid)
                {
                    showSearchingUI = false;
                    break;
                }
            }
            m_searchingForPlaneUI.SetActive(showSearchingUI);



            //For moving the 3d Model on the scene. After 3D Model has been Rendered and Selected.
            if (Input.touchCount == 1 && objectRendered)
            {
                TrackableHit myHit;
                Touch        mytouch = Input.GetTouch(0);

                if (mytouch.phase == TouchPhase.Stationary || mytouch.phase == TouchPhase.Moved)
                {
                    // If Touch RayCast hits the tracked plane, get the co-ordinates and change the position of the 3d Model
                    if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(mytouch.position), raycastFilter, out myHit))
                    {
                        andyObject.transform.position = Vector3.Lerp(andyObject.transform.position, myHit.Point, Time.deltaTime);
                    }
                }
            }


            // When there are more than 2 3d Models on the scene. This code helps to select different models.
            if (Input.touchCount == 1 && !object_Selected_From_Menu && objectRendered)
            {
                RaycastHit myHit;
                Touch      myTouch = Input.GetTouch(0);
                Ray        ray     = m_firstPersonCamera.ScreenPointToRay(myTouch.position);
                // When RayCasting, if it hits the collider and user taps twice then it becomes the new selected object.
                if (Physics.Raycast(ray, out myHit, Mathf.Infinity) && myTouch.tapCount == 2)
                {
                    _ShowAndroidToastMessage(myHit.collider.gameObject.name);
                    andyObject             = myHit.collider.gameObject;
                    model_Selected_onScene = true;
                }

                // If touch Raycast hits the collider and the user taps thrice then it destroys the gameobject.
                if (Physics.Raycast(ray, out myHit, Mathf.Infinity) && myTouch.tapCount == 3)
                {
                    Destroy(myHit.collider.gameObject);
                }
            }


            // Rotating the 3d Model when two fingers is pressed
            if (Input.touchCount == 2)
            {
                if (!rotating)
                {
                    startVector = Input.GetTouch(1).position - Input.GetTouch(0).position;
                    rotating    = startVector.sqrMagnitude > rotGestureWidth * rotGestureWidth;
                }

                else
                {
                    // Figuring out How to Calculate the Exact angle between two fingers when user performs the twist gesture.
                    var currVector  = Input.GetTouch(1).position - Input.GetTouch(0).position;
                    var angleOffset = Vector2.Angle(startVector, currVector);
                    var LR          = Vector3.Cross(startVector, currVector);

                    // Rotates the current selected object.
                    andyObject.transform.Rotate(0, 2.5f, 0);
                }
            }

            else
            {
                rotating = false;
            }

            TrackableHit hit;
            Touch        touch;

            if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
            {
                return;
            }
            if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit) && object_Selected_From_Menu)
            {
                objectRendered            = true;
                object_Selected_From_Menu = false;
                // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                // world evolves.
                anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
                // from the anchor's tracking.
                andyObject = Instantiate(m_andyAndroidPrefab, hit.Point, Quaternion.identity,
                                         anchor.transform);

                // Andy should look at the camera but still be flush with the plane.
                andyObject.transform.LookAt(m_firstPersonCamera.transform);
                andyObject.transform.rotation = Quaternion.Euler(0.0f,
                                                                 andyObject.transform.rotation.eulerAngles.y, andyObject.transform.rotation.z);


                // Use a plane attachment component to maintain Andy's y-offset from the plane
                // (occurs after anchor updates).
                andyObject.GetComponent <PlaneAttachment>().Attach(hit.Plane);
            }

            anchor.transform.Rotate(Vector3.right * Time.deltaTime, Space.World);
        }
Exemple #30
0
        /// <summary>
        /// The Unity Update() method.
        /// </summary>
        public void Update()
        {
            _QuitOnConnectionErrors();

            // The tracking state must be FrameTrackingState.Tracking in order to access the Frame.
            if (Frame.TrackingState != FrameTrackingState.Tracking)
            {
                const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
                Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
                return;
            }

            Screen.sleepTimeout = SleepTimeout.NeverSleep;
            Frame.GetNewPlanes(ref m_newPlanes);

            // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
            for (int i = 0; i < m_newPlanes.Count; i++)
            {
                // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
                // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
                // coordinates.
                GameObject planeObject = Instantiate(m_trackedPlanePrefab, Vector3.zero, Quaternion.identity,
                                                     transform);
                planeObject.GetComponent <TrackedPlaneVisualizer>().SetTrackedPlane(m_newPlanes[i]);

                // Apply a random color and grid rotation.
                planeObject.GetComponent <Renderer>().material.SetColor("_GridColor", m_planeColors[Random.Range(0,
                                                                                                                 m_planeColors.Length - 1)]);
                planeObject.GetComponent <Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
            }

            // Disable the snackbar UI when no planes are valid.
            bool showSearchingUI = true;

            Frame.GetAllPlanes(ref m_allPlanes);
            for (int i = 0; i < m_allPlanes.Count; i++)
            {
                if (m_allPlanes[i].IsValid)
                {
                    showSearchingUI = false;

                    /*if (!m_mapAnchor || m_lowestPlane == null || !m_lowestPlane.IsValid || m_allPlanes[i].Position.y < m_lowestPlane.Position.y) {
                     *      //m_mapGameObject.transform.position = m_allPlanes[i].Position;
                     *      //m_mapGameObject.transform.localScale = new Vector3 (1,1,1);
                     *      m_mapAnchor = Session.CreateAnchor (new Vector3 (m_allPlanes [i].Position.x, m_allPlanes [i].Position.y - 1.5F, m_allPlanes [i].Position.z), Quaternion.identity);
                     *      m_mapGameObject.transform.parent = m_mapAnchor.transform;
                     *      m_mapGameObject.transform.localScale = new Vector3 (1,1,1);
                     *      m_mapGameObject.transform.localPosition = new Vector3(0,-10,0);
                     *      m_mapGameObject.transform.localRotation = Quaternion.identity;
                     *      //m_mapGameObject.GetComponent<PlaneAttachment> ().Attach (m_allPlanes [i]);
                     *      m_lowestPlane = m_allPlanes [i];
                     * }
                     * //m_mapGameObject.transform.position = new Vector3(m_mapGameObject.transform.position.x, m_allPlanes[i].Position.y - 1.5F,
                     * //	m_mapGameObject.transform.position.z);
                     * //m_mapGameObject.GetComponent<PlaneAttachment> ().Attach (m_allPlanes [i]);
                     *
                     * //break;
                     */
                    if (m_mapAnchor == null)
                    {
                        m_mapAnchor = Session.CreateAnchor(Vector3.zero, Quaternion.identity);
                        m_mapGameObject.transform.parent        = m_mapAnchor.transform;
                        m_mapGameObject.transform.localScale    = new Vector3(1, 1, 1);
                        m_mapGameObject.transform.localPosition = new Vector3(0, 0, 0);
                        m_mapGameObject.transform.localRotation = Quaternion.identity;

                        string userId = FireBaseAuthHandler.user.UserId;
                        dbref.Child("users").Child(userId).Child("notes").GetValueAsync().ContinueWith(Task =>
                        {
                            if (Task.IsCompleted)
                            {
                                DataSnapshot snapshot = Task.Result;
                                foreach (DataSnapshot snap1 in snapshot.Children)
                                {
                                    foreach (DataSnapshot raw_note in snap1.Children)
                                    {
                                        Note note     = JsonUtility.FromJson <Note>(raw_note.GetRawJsonValue());
                                        Vector3 point = new Vector3((float)note.loclat, 0, (float)note.loclong);
                                        // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                                        // world evolves.
                                        var anchor = Session.CreateAnchor(point, Quaternion.identity);

                                        // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
                                        // from the anchor's tracking.
                                        var andyObject = Instantiate(m_andyAndroidPrefab, point, Quaternion.identity,
                                                                     anchor.transform);

                                        // Andy should look at the camera but still be flush with the plane.
                                        andyObject.transform.LookAt(m_firstPersonCamera.transform);
                                        andyObject.transform.rotation = Quaternion.Euler(0.0f,
                                                                                         andyObject.transform.rotation.eulerAngles.y, andyObject.transform.rotation.z);
                                    }
                                }
                            }
                        });
                    }
                    break;
                }
            }

            m_searchingForPlaneUI.SetActive(showSearchingUI);

            Touch touch;

            if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
            {
                return;
            }

            TrackableHit     hit;
            TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;

            if (Session.Raycast(m_firstPersonCamera.ScreenPointToRay(touch.position), raycastFilter, out hit))
            {
                // write to FireBase
                string userId    = FireBaseAuthHandler.user.UserId;
                Note   note      = new Note(hit.Point.x, hit.Point.y, "Note goes here");
                string json      = JsonUtility.ToJson(note);
                string keyToPush = dbref.Child("users").Child(userId).Child("notes").Push().Key;
                dbref.Child("users").Child(userId).Child("notes").Child(keyToPush).SetRawJsonValueAsync(json);

                // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                // world evolves.
                var anchor = Session.CreateAnchor(hit.Point, Quaternion.identity);

                // Intanstiate an Andy Android object as a child of the anchor; it's transform will now benefit
                // from the anchor's tracking.
                var andyObject = Instantiate(m_andyAndroidPrefab, hit.Point, Quaternion.identity,
                                             anchor.transform);

                // Andy should look at the camera but still be flush with the plane.
                andyObject.transform.LookAt(m_firstPersonCamera.transform);
                andyObject.transform.rotation = Quaternion.Euler(0.0f,
                                                                 andyObject.transform.rotation.eulerAngles.y, andyObject.transform.rotation.z);

                // Use a plane attachment component to maintain Andy's y-offset from the plane
                // (occurs after anchor updates).
                andyObject.GetComponent <PlaneAttachment>().Attach(hit.Plane);
            }
        }