Skip to content

Instantly share code, notes, and snippets.

@dilmerv
Created April 27, 2020 03:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dilmerv/7d6306b74a0e9a37b1c1b5fa254227f3 to your computer and use it in GitHub Desktop.
Save dilmerv/7d6306b74a0e9a37b1c1b5fa254227f3 to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.XR.Interaction.Toolkit.AR;
public class ARPlacementInteractableSingle : ARBaseGestureInteractable
{
[SerializeField]
[Tooltip("A GameObject to place when a raycast from a user touch hits a plane.")]
public GameObject placementPrefab;
[SerializeField]
[Tooltip("Callback event executed after object is placed.")]
private ARObjectPlacementEvent onObjectPlaced;
private GameObject placementObject;
private static List<ARRaycastHit> hits = new List<ARRaycastHit>();
private static GameObject trackablesObject;
protected override bool CanStartManipulationForGesture(TapGesture gesture)
{
if (gesture.StartPosition.IsPointOverUIObject())
return false;
// Allow for test planes
if (gesture.TargetObject == null || gesture.TargetObject.layer == 9)
return true;
return false;
}
protected override void OnEndManipulation(TapGesture gesture)
{
if(Input.touchCount == 0)
{
return;
}
var touch = Input.GetTouch(0);
var touchPosition = touch.position;
bool isOverUI = touchPosition.IsPointOverUIObject();
if (gesture.WasCancelled)
return;
// If gesture is targeting an existing object we are done.
// Allow for test planes
if (gesture.TargetObject != null && gesture.TargetObject.layer != 9)
return;
//Checking if touch is over UI element
if (isOverUI)
{
Debug.Log("UI is touched");
}
Debug.Log(isOverUI);
// if (!isOverUI && GestureTransformationUtility.Raycast(gesture.StartPosition, hits, TrackableType.PlaneWithinPolygon))
// Raycast against the location the player touched to search for planes.
if (GestureTransformationUtility.Raycast(gesture.StartPosition, hits, TrackableType.PlaneWithinPolygon))
{
var hit = hits[0];
// Use hit pose and camera pose to check if hittest is from the
// back of the plane, if it is, no need to create the anchor.
if (Vector3.Dot(Camera.main.transform.position - hit.pose.position, hit.pose.rotation * Vector3.up) < 0)
return;
//if(placementObject == null)
//{
placementObject = Instantiate(placementPrefab, hit.pose.position, hit.pose.rotation);
// Create anchor to track reference point and set it as the parent of placementObject.
// TODO: this should update with a reference point for better tracking.
var anchorObject = new GameObject("PlacementAnchor");
anchorObject.transform.position = hit.pose.position;
anchorObject.transform.rotation = hit.pose.rotation;
placementObject.transform.parent = anchorObject.transform;
// Find trackables object in scene and use that as parent
if (trackablesObject == null)
trackablesObject = GameObject.Find("Trackables");
if (trackablesObject != null)
anchorObject.transform.parent = trackablesObject.transform;
onObjectPlaced?.Invoke(this, placementObject);
//}
}
}
}
@nosarious
Copy link

I am using version 5.0 of ARFoundation. There is a problem in this code which I am struggling to fix about where Raycasting occurs.

Assets/Scenes/ceiling/ARPlacementInteractableSingle.cs(65,13): warning CS0618: 'GestureTransformationUtility.Raycast(Vector2, List, TrackableType)' is obsolete: 'Raycast has been deprecated. Use Raycast with updated signature instead.'

this line (in my version, line 64 in yours):
if (GestureTransformationUtility.Raycast(gesture.StartPosition, hits, TrackableType.PlaneWithinPolygon))

how do I implement 'use raycast with updated signature instead'?

(BTW your code and video have been incredibly useful for solving some problems with the Unity documentation)

@celiksai
Copy link

Hello could you solve this problem? I have the same too...

@Umar10101
Copy link

    if (GestureTransformationUtility.Raycast(gesture.startPosition, hits, xrOrigin, TrackableType.PlaneWithinPolygon)) 

this is supported format for updated raycast.

@Umar10101
Copy link

using UnityEngine.XR.Interaction.Toolkit.AR;
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

public class Singleplacement : ARBaseGestureInteractable
{
[SerializeField]
private GameObject placementPrefab;

[SerializeField]
private ARObjectPlacementEvent onObjectPlaced;

private GameObject placementObject;
private static List<ARRaycastHit> hits = new List<ARRaycastHit>();
private static GameObject trackablesObject;

protected override bool CanStartManipulationForGesture(TapGesture gesture)
{
    if (gesture.targetObject == null)
    {
        return true;
    }
    return false;
}

protected override void OnEndManipulation(TapGesture gesture)
{
    if (gesture.targetObject != null)
    {
        return;
    }
    if (GestureTransformationUtility.Raycast(gesture.startPosition, hits, xrOrigin, TrackableType.PlaneWithinPolygon))
    {
        var hitPose = hits[0].pose;

        // Allow a new game object for AR placement object
        if (placementObject == null)
        {
            placementObject = PlaceObject(hitPose);

            onObjectPlaced?.Invoke(this, placementObject);
        }
    }
}

// Edited method to handle placement similar to ARPlacementInteractable
protected virtual GameObject PlaceObject(Pose pose)
{
    var placementObject = Instantiate(placementPrefab, pose.position, pose.rotation);

    // Create anchor to track reference point and set it as the parent of placementObject.
    var anchor = new GameObject("PlacementAnchor").transform;
    anchor.position = pose.position;
    anchor.rotation = pose.rotation;
    placementObject.transform.parent = anchor;

    // Use Trackables object in scene to use as parent
    var trackablesParent = xrOrigin != null
        ? xrOrigin.TrackablesParent
        : (xrOrigin != null ? xrOrigin.TrackablesParent : null);

    if (trackablesParent != null)
    {
        anchor.parent = trackablesParent;
    }

    return placementObject;
}

}
this is a working script for single prefab placement

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment