Reputation: 901
Disclaimer: I'm pretty new to Unity3D and ARCore, so please bear with me.
I'm using ARCore in Unity3D to create a scene where the user can select models in a ScrollView
on the screen and place them using Google's ARCore framework.
So far I have it working; the user touches a model in the ScrollView
(which is indicated on-screen in a Panel
as the currently selected model, as my plans are to have the ScrollView
toggle visibility for more screen view space).
The problem is that when a user selects a model, ARCore is placing a model on the detected plane behind where the ScrollView
and selected model Panel
objects are (even when you first touch to start scrolling the ScrollView
). See below to help visualize.
How can I get ARCore to not place the object behind the ScrollView
and Panel
? What I've tried is adding to my controller (which is really just the Google HelloARController) a collection of objects that I want to block ARCore's Raycast
and iterate through them with a foreach
to see if the Raycast
hits the GameObjects
in the collection
Touch touch;
if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
{
return;
}
//my code; above is Google's
foreach (var item in BlockingObjects) { //BlockingObjects is a List<GameObject>
if (IsTouchInObject(FirstPersonCamera.ScreenPointToRay(touch.position), item)) {
return;
}
}
//end of my code; below is Google's
TrackableHit hit;
TrackableHitFlag raycastFilter = TrackableHitFlag.PlaneWithinBounds | TrackableHitFlag.PlaneWithinPolygon;
With the IsTouchInObject
function defined like this:
private bool IsTouchInObject(Ray ray, GameObject obj) {
RaycastHit rch;
Physics.Raycast (ray, out rch);
return (rch.collider != null);
}
The thing that is failing is that rch.collider
is always null
(I know that I'm not testing against the object at all, I'll worry about that once I can get the Raycast
to actually collide with a GameObject
). I've tried using Physics
/Physics2D
with RaycastHit
/RacastHit2D
and attaching BoxCollider
/BoxCollider2D
components to the objects I want to detect the hit on, but nothing I've done is working.
(This solution was taken from something on the Unity3D forums in which someone had a similar issue, but not with AR, with their own 3D world with a 2D overlay. I can't find that forum post to provide reference, sorry).
Any help would be greatly appreciated.
EDIT/NOTE: I've now noticed there is a Graphic Raycaster
component on the Canvas
, which contains my ScrollView
and Panel
. I've tried setting the Blocking Objects
to Two D
(while adding a Box Collider 2D
to the ScrollView
and Panel
) and Blocking Mask
to Ignore Raycast
(and a couple other things) to no avail. Is there a combination of values for these properties that could do it?
In the spirit of today's date:
Upvotes: 4
Views: 2230
Reputation: 180
This is my first answer on StackOverflow so bear with me. I'm building a similar app where you can select different models from a UI Panel in unity and place the model on the detected plane in real world. The only hack I was able to devise to overcome the problem you're having is to do the following :
In your HelloARController.CS, initialize a bool 'place_model' (or any name you want) and set it to false. Now you need to scroll to the portion where you augment your model in the real world.
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(m_andy, 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);
andyObject.AddComponent<BoxCollider>();
// Use a plane attachment component to maintain Andy's y-offset from the plane
// (occurs after anchor updates).
andyObject.GetComponent<PlaneAttachment>().Attach(hit.Plane);
}
Change the above code to something like this :
if (place_model){ // changed portion
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(m_andy, 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);
andyObject.AddComponent<BoxCollider>();
// Use a plane attachment component to maintain Andy's y-offset from the plane
// (occurs after anchor updates).
andyObject.GetComponent<PlaneAttachment>().Attach(hit.Plane);
place_model = false // changed portion
}
}
Now you won't be able to place a model no matter what. Because the script augmenting the model to the real world isn't running, as the bool 'place_model' is set to false. Now, just when you want to augment the model to the real world, you select the model from your panel and set the 'place_model' bool to true. This is simple as you just need to set an event listener to your button, setting the bool to true when you click the button. The next time you touch on the tracked plane, your model gets augmented.
Hope this solves your problem...
Upvotes: 3
Reputation: 644
Have you tried wrapping the Raycast with:
if (!EventSystem.current.IsPointerOverGameObject(touch.fingerId)) {...}
https://answers.unity.com/questions/1406243/ui-in-arcore-helloar-example.html
Upvotes: 6