TheUnityWorkbench / tuw-arfoundation-demo

Other
103 stars 89 forks source link

ARSessionOrigin has no member Raycast #1

Closed Schaggo closed 3 years ago

Schaggo commented 5 years ago

I followed your tutorial on YouTube. Using unity 2018.3 everything works like a charm. Trying on 2019.2 I get the error that ARSessionOrigin does not contain a definition for Raycast.

So far I couldn't find a reference to raycasting in the documentation.

Any hint?

Kocurrr commented 5 years ago

There is a new component called ARRaycastManager. You should add it to the same GameObject as ARSessionOrigin component in the tutorial and than you can perform Raycast methods using that ARRaycastManager. πŸ˜„

Schaggo commented 5 years ago

Thanks! I managed to find the migration docs (duh!) but still struggle to instantiate the placement indicator. Xcode spits out a NullReference within UpdatePlacementPose().

Kocurrr commented 5 years ago

I had the same problem, try changing Camera.current to Camera.main

Schaggo commented 5 years ago

Thanks, man! I tried with a public camera reference to the arcam, but that didn't work. Saved me a headache!

anesask commented 5 years ago

I have found migration docs, followed all...but still have not figured out how it really works...

Schaggo commented 5 years ago

here have my script:

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR; using UnityEngine.XR.ARSubsystems; using System;

public class ArTabToPlaceObject : MonoBehaviour { public GameObject objectToPlace; public GameObject placementIndicator; private Camera myCamera; private ARSessionOrigin arOrigin; private ARRaycastManager raycastManager; private Pose placementPose; private bool placementPoseIsValid = false;

void Start()
{
    arOrigin = FindObjectOfType<ARSessionOrigin>();
    raycastManager = FindObjectOfType<ARRaycastManager>();

}

void Update()
{
    UpdatePlacementPose();
    UpdatePlacementIndicator();

    if (placementPoseIsValid &&  Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
    {
        PlaceObject();
    }
}

private void PlaceObject()
{
    Instantiate(objectToPlace, placementPose.position, placementPose.rotation);
}

private void UpdatePlacementIndicator()
{
    if (placementPoseIsValid)
    {
        placementIndicator.SetActive(true);
        placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);
    }
    else
    {
        placementIndicator.SetActive(false);
    }
}

private void UpdatePlacementPose()
{
    var screenCenter = Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
    var hits = new List<ARRaycastHit>();
    raycastManager.Raycast(screenCenter, hits, TrackableType.Planes);

    placementPoseIsValid = hits.Count > 0;
    if (placementPoseIsValid)
    {
        placementPose = hits[0].pose;

        var cameraForward = Camera.current.transform.forward;
        var cameraBearing = new Vector3(cameraForward.x, 0, cameraForward.z).normalized;
        placementPose.rotation = Quaternion.LookRotation(cameraBearing);
    }
}

}

anesask commented 5 years ago

here have my script:

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR; using UnityEngine.XR.ARSubsystems; using System;

public class ArTabToPlaceObject : MonoBehaviour { public GameObject objectToPlace; public GameObject placementIndicator; private Camera myCamera; private ARSessionOrigin arOrigin; private ARRaycastManager raycastManager; private Pose placementPose; private bool placementPoseIsValid = false;

void Start()
{
    arOrigin = FindObjectOfType<ARSessionOrigin>();
    raycastManager = FindObjectOfType<ARRaycastManager>();

}

void Update()
{
    UpdatePlacementPose();
    UpdatePlacementIndicator();

    if (placementPoseIsValid &&  Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
    {
        PlaceObject();
    }
}

private void PlaceObject()
{
    Instantiate(objectToPlace, placementPose.position, placementPose.rotation);
}

private void UpdatePlacementIndicator()
{
    if (placementPoseIsValid)
    {
        placementIndicator.SetActive(true);
        placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);
    }
    else
    {
        placementIndicator.SetActive(false);
    }
}

private void UpdatePlacementPose()
{
    var screenCenter = Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
    var hits = new List<ARRaycastHit>();
    raycastManager.Raycast(screenCenter, hits, TrackableType.Planes);

    placementPoseIsValid = hits.Count > 0;
    if (placementPoseIsValid)
    {
        placementPose = hits[0].pose;

        var cameraForward = Camera.current.transform.forward;
        var cameraBearing = new Vector3(cameraForward.x, 0, cameraForward.z).normalized;
        placementPose.rotation = Quaternion.LookRotation(cameraBearing);
    }
}

}

That was quick! I will try it! Thanks a loooot!

Schaggo commented 5 years ago

i also had the problem, that I tried to use the placement indicator as a prefab. nope - you have to actually have it in the scene

anesask commented 5 years ago

i also had the problem, that I tried to use the placement indicator as a prefab. nope - you have to actually have it in the scene

Didn't managed it to work... Can I look in your source project?

Schaggo commented 5 years ago

I just used the git and changed the script.

Schaggo commented 5 years ago

What isn't working?

anesask commented 5 years ago

What isn't working?

raycastManager.Raycast(screenCenter, hits, **TrackableType.Planes**);

TrackableType throws me error...

Schaggo commented 5 years ago

using UnityEngine.XR.ARSubsystems;

Organwolf commented 5 years ago

There is a new component called ARRaycastManager. You should add it to the same GameObject as ARSessionOrigin component in the tutorial and than you can perform Raycast methods using that ARRaycastManager. πŸ˜„

How is this done exactly? Right now my indicator is hanging in mid air. Most likely because the raycastManager isn't found upon start? Do I have to add a new GameObject and attach something containing the ARRaycastManager?

Organwolf commented 5 years ago

using UnityEngine.XR.ARSubsystems;

I'm using the XR.ARSubsystem and I get the same results no matter if the var screenCenter is Camera.current or Camera.main. I have also read the documentation for the two Raycast methods on unitys homepage. Unfortunately I don't understand this stuff good enough πŸ˜„

Schaggo commented 5 years ago

I think I had a similar issue where the indicator wasn't flat to the surface, because I forgot to put the quad in an empty game object. Another thing is to reference the indicator that is actually in the scene not a prefab.

Organwolf commented 5 years ago

Wow, thank you for the amazingly quick answer. It isn't that it doesn't lay flat. The position of the indicator is that of the the phone when the app starts. It's worth to mention that I'm using ARFoundation in combination with ARCore on an Android phone.

I have an interaction object which has the ARTapToPlaceObject script as well as a reference to the placement indicator. I'm not sure if I placed the quad in an empty game object. How do I check that? The quad is visible and a child to the placement indicator.

I've also chosen to use another .png for the indicator but that can't matter one bit.

Organwolf commented 5 years ago

Also I'm using Unity 2018.4.0f1

Schaggo commented 5 years ago

Ah that might be the Problem. This threat is referring to 2019.2 and arfoundation 2.02.

I think if you just download the git and run it, you should be good to go. Although I haven’t tested on android.

Organwolf commented 5 years ago

I got it to work via a course I'm taking and by talking with some friends that know more about Unity. The course is: Handheld AR App Development with Unity and you can audit the course for free. Thanks for the help Schaggo!

Barathwaja commented 5 years ago

Its not working for me. I couldn't view the placement indicator at all first even though i have added that gameobject

nicolocarpignoli commented 5 years ago

@anesask try with importing also arsubstystem: using UnityEngine.XR.ARSubsystems;

flyphoenixhotel commented 5 years ago

I got it to work via a course I'm taking and by talking with some friends that know more about Unity. The course is: Handheld AR App Development with Unity and you can audit the course for free. Thanks for the help Schaggo!

do you mind telling me exactly how you got the indicator to be placed on surfaces instead of it appearing wherever the camera starts? I'm having the same problem right now πŸ˜„

eckmLJE commented 5 years ago

Do you only need to add ARRaycastManager in the script, or do you also need to add it as a component in the hierarchy? If the latter, how do you do that? It's not available under the XR menu like AR Session Origin.

Organwolf commented 5 years ago

Add the ARRaycastManager component to the AR Session Origin. Then you use the raycastmanager in your script to perform the raycasts. You do not need to add it to the Hierarcy.

eckmLJE commented 5 years ago

How do I add the ARRaycastManager component to the AR Session Origin?

Organwolf commented 5 years ago

Click on the "Add Component" and search for ARRaycastManager. In the script either use Getcomponent or add it using [SerializeField]. Here is a simple script using the mentioned manager.

using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems;

public class RaycastObject : MonoBehaviour { [SerializeField] ARRaycastManager raycastManager; [SerializeField] GameObject objectPrefab;

private GameObject placedObject;
private List<ARRaycastHit> s_Hits = new List<ARRaycastHit>();
private bool isObjectPlaced = false;

void Update()
{
    if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
    {

        Touch touch = Input.GetTouch(0);
        bool hitFound = raycastManager.Raycast(touch.position, s_Hits, TrackableType.Planes);

        if (hitFound && !isObjectPlaced)
        {
            var hit = s_Hits[0];
            Vector3 newPosition = hit.pose.position;
            Quaternion newRotation = hit.pose.rotation;

            placedObject = Instantiate(objectPrefab, newPosition, newRotation);
            isObjectPlaced = true;
        }
        else
        {
            var hit = s_Hits[0];
            Vector3 newPosition = hit.pose.position;
            Quaternion newRotation = hit.pose.rotation;

            placedObject.transform.position = newPosition;
            placedObject.transform.rotation = newRotation;
        }
    }
}

}

eckmLJE commented 5 years ago

Edit: I'm logging from my script and I'm not getting any hits from the raycast. placementPoseIsValid is always false. How do I troubleshoot the Raycast Manager?

Thanks for your continued help, @Organwolf! I have added the AR Raycast Manager to the AR Session Origin object. I'm no longer getting any errors in my script (below) using the raycast method on the raycast manager, which is a win.

But when building and running the app on my Android device I'm still not seeing the placement indicator. πŸ€·β€β™‚

Here's my ar session origin and my script in the hierarchy: https://imgur.com/a/Roci25f

The script itself is below. I know this is beyond the scope of what you helped me with but if anything jumps out at out you please let me know. Thanks again.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR;
using UnityEngine.XR.ARSubsystems;
using System;

public class ARTapToPlaceObject : MonoBehaviour
{
    public GameObject objectToPlace;
    public GameObject placementIndicator;
    private Camera myCamera;
    private ARSessionOrigin arOrigin;
    private ARRaycastManager raycastManager;
    private Pose placementPose;
    private bool placementPoseIsValid = false;

    void Start()
    {
        arOrigin = FindObjectOfType<ARSessionOrigin>();
        raycastManager = FindObjectOfType<ARRaycastManager>();

    }

    void Update()
    {
        UpdatePlacementPose();
        UpdatePlacementIndicator();
        Debug.Log(placementPoseIsValid);

        if (placementPoseIsValid && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
        {
            PlaceObject();
        }
    }

    private void PlaceObject()
    {
        Instantiate(objectToPlace, placementPose.position, placementPose.rotation);
    }

    private void UpdatePlacementIndicator()
    {
        if (placementPoseIsValid)
        {
            placementIndicator.SetActive(true);
            placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);
        }
        else
        {
            placementIndicator.SetActive(false);
        }
    }

    private void UpdatePlacementPose()
    {
        var screenCenter = Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
        var hits = new List<ARRaycastHit>();
        raycastManager.Raycast(screenCenter, hits, TrackableType.Planes);
        Debug.Log(hits);

        placementPoseIsValid = hits.Count > 0;
        if (placementPoseIsValid)
        {
            placementPose = hits[0].pose;

            var cameraForward = Camera.main.transform.forward;
            var cameraBearing = new Vector3(cameraForward.x, 0, cameraForward.z).normalized;
            placementPose.rotation = Quaternion.LookRotation(cameraBearing);
        }
    }

}
Schaggo commented 5 years ago

Edit: I'm logging from my script and I'm not getting any hits from the raycast. placementPoseIsValid is always false. How do I troubleshoot the Raycast Manager?

Thanks for your continued help, @Organwolf! I have added the AR Raycast Manager to the AR Session Origin object. I'm no longer getting any errors in my script (below) using the raycast method on the raycast manager, which is a win.

But when building and running the app on my Android device I'm still not seeing the placement indicator. πŸ€·β€β™‚

Here's my ar session origin and my script in the hierarchy: https://imgur.com/a/Roci25f

The script itself is below. I know this is beyond the scope of what you helped me with but if anything jumps out at out you please let me know. Thanks again.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR;
using UnityEngine.XR.ARSubsystems;
using System;

public class ARTapToPlaceObject : MonoBehaviour
{
    public GameObject objectToPlace;
    public GameObject placementIndicator;
    private Camera myCamera;
    private ARSessionOrigin arOrigin;
    private ARRaycastManager raycastManager;
    private Pose placementPose;
    private bool placementPoseIsValid = false;

    void Start()
    {
        arOrigin = FindObjectOfType<ARSessionOrigin>();
        raycastManager = FindObjectOfType<ARRaycastManager>();

    }

    void Update()
    {
        UpdatePlacementPose();
        UpdatePlacementIndicator();
        Debug.Log(placementPoseIsValid);

        if (placementPoseIsValid && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
        {
            PlaceObject();
        }
    }

    private void PlaceObject()
    {
        Instantiate(objectToPlace, placementPose.position, placementPose.rotation);
    }

    private void UpdatePlacementIndicator()
    {
        if (placementPoseIsValid)
        {
            placementIndicator.SetActive(true);
            placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);
        }
        else
        {
            placementIndicator.SetActive(false);
        }
    }

    private void UpdatePlacementPose()
    {
        var screenCenter = Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
        var hits = new List<ARRaycastHit>();
        raycastManager.Raycast(screenCenter, hits, TrackableType.Planes);
        Debug.Log(hits);

        placementPoseIsValid = hits.Count > 0;
        if (placementPoseIsValid)
        {
            placementPose = hits[0].pose;

            var cameraForward = Camera.main.transform.forward;
            var cameraBearing = new Vector3(cameraForward.x, 0, cameraForward.z).normalized;
            placementPose.rotation = Quaternion.LookRotation(cameraBearing);
        }
    }

}

I just revisited the project and upgraded to the latest frameworks (ArFoundation 2.13 /Arkit 2.11/ Unity 2019.2.4f1)

Your script worked from the start so there must be something in your editor settings. Do you get a NullReference warning when hitting play or in Xcode when running the app?

eckmLJE commented 5 years ago

I'm actually running this on a Pixel 2 with ARCore.

2019.2.4f1 Pixel 2 AR Foundation 2.0.2 ARCore XR Plugin 2.0.2

If I change the TrackableType.Planes to TrackableType.All then I get intermittent hits and the placement indicator will draw, but it's patchy in and out.

ulisesmora commented 4 years ago

@eckmLJE

try changing the option inside your arcamera tracker pose to update. i have the same problem

eckmLJE commented 4 years ago

@ulisesmora Sorry, could you rephrase that? I'm not following.

jikkimi commented 4 years ago

There is a new component called ARRaycastManager. You should add it to the same GameObject as ARSessionOrigin component in the tutorial and than you can perform Raycast methods using that ARRaycastManager. πŸ˜„

How is this done exactly? Right now my indicator is hanging in mid air. Most likely because the raycastManager isn't found upon start? Do I have to add a new GameObject and attach something containing the ARRaycastManager?

I have the same issue. Did you resolve it? If so, please let me know. I'm also trying with an android phone by the latest version of ARFoundation.

andreac commented 4 years ago

@ulisesmora i tried changing the ar camera option to update, but it didin't solve..

Someone solve it??

LIfeZ0 commented 4 years ago

@andreac add an ar raycast manager component to your ar session origin, i think it will work

lyannechu commented 4 years ago

Edit: I'm logging from my script and I'm not getting any hits from the raycast. placementPoseIsValid is always false. How do I troubleshoot the Raycast Manager? Thanks for your continued help, @Organwolf! I have added the AR Raycast Manager to the AR Session Origin object. I'm no longer getting any errors in my script (below) using the raycast method on the raycast manager, which is a win. But when building and running the app on my Android device I'm still not seeing the placement indicator. πŸ€·β€β™‚ Here's my ar session origin and my script in the hierarchy: https://imgur.com/a/Roci25f The script itself is below. I know this is beyond the scope of what you helped me with but if anything jumps out at out you please let me know. Thanks again.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR;
using UnityEngine.XR.ARSubsystems;
using System;

public class ARTapToPlaceObject : MonoBehaviour
{
    public GameObject objectToPlace;
    public GameObject placementIndicator;
    private Camera myCamera;
    private ARSessionOrigin arOrigin;
    private ARRaycastManager raycastManager;
    private Pose placementPose;
    private bool placementPoseIsValid = false;

    void Start()
    {
        arOrigin = FindObjectOfType<ARSessionOrigin>();
        raycastManager = FindObjectOfType<ARRaycastManager>();

    }

    void Update()
    {
        UpdatePlacementPose();
        UpdatePlacementIndicator();
        Debug.Log(placementPoseIsValid);

        if (placementPoseIsValid && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
        {
            PlaceObject();
        }
    }

    private void PlaceObject()
    {
        Instantiate(objectToPlace, placementPose.position, placementPose.rotation);
    }

    private void UpdatePlacementIndicator()
    {
        if (placementPoseIsValid)
        {
            placementIndicator.SetActive(true);
            placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);
        }
        else
        {
            placementIndicator.SetActive(false);
        }
    }

    private void UpdatePlacementPose()
    {
        var screenCenter = Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
        var hits = new List<ARRaycastHit>();
        raycastManager.Raycast(screenCenter, hits, TrackableType.Planes);
        Debug.Log(hits);

        placementPoseIsValid = hits.Count > 0;
        if (placementPoseIsValid)
        {
            placementPose = hits[0].pose;

            var cameraForward = Camera.main.transform.forward;
            var cameraBearing = new Vector3(cameraForward.x, 0, cameraForward.z).normalized;
            placementPose.rotation = Quaternion.LookRotation(cameraBearing);
        }
    }

}

I just revisited the project and upgraded to the latest frameworks (ArFoundation 2.13 /Arkit 2.11/ Unity 2019.2.4f1)

Your script worked from the start so there must be something in your editor settings. Do you get a NullReference warning when hitting play or in Xcode when running the app?

I'm definitely getting the NullReferenceException error on UpdatePlacementPose(). If you have a fix for this, I would be so grateful!

Han-IChun commented 3 years ago

In case anyone is still interested in solving NullReferenceException error. There are two changes to solve this issue:

  1. Change C# script following pull request in this repo.
  2. Add 'AR Raycast manager' component to 'AR Session Origin'

It works for me on AR foundation 4.1.5 and ARKit 4.1.5. Cheers.

ss-cmd commented 3 years ago

I followed your tutorial on YouTube. Using unity 2018.3 everything works like a charm. Trying on 2019.2 I get the error that ARSessionOrigin does not contain a definition for Raycast.

So far I couldn't find a reference to raycasting in the documentation.

Any hint?

Hi, I have the same issue. I add ar raycast manager in ar session origin but no prefab shows up... what's your solution, does it means I need to add a script to modofiy it?

Schaggo commented 3 years ago

Check out the demo projects