Search Unity

Question How to place AR object using 2 points?

Discussion in 'AR' started by aleksos54, Jul 25, 2021.

  1. aleksos54

    aleksos54

    Joined:
    Jul 12, 2021
    Posts:
    4
    Hi,
    I want to make App where I place house on the plane. Right now I have placement indicator finding floor plane and when I click the screen the house is being placed on the floor in this point but the rotation of the house depends on my angle to the placement indicator.
    I want to place the house in the exact position and I would like to use 2 points to place the house because I dont want the rotation to depends on where I stay.

    Right now my code looks like this:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.XR.ARFoundation;
    5. using UnityEngine.XR.ARSubsystems;
    6.  
    7. public class ARPlacement : MonoBehaviour
    8. {
    9.     public GameObject arObjectToSpawn;
    10.     public GameObject placementIndicator;
    11.     private GameObject spawnedObject;
    12.  
    13.     private Pose placementPose;
    14.     private ARRaycastManager aRRaycastManager;
    15.     private bool placementPoseIsValid = false;
    16.     private List<ARRaycastHit> _hits = new List<ARRaycastHit>();
    17.     // Start is called before the first frame update
    18.     void Start()
    19.     {
    20.         aRRaycastManager = FindObjectOfType<ARRaycastManager>();
    21.  
    22.     }
    23.  
    24.     //update placement indicator kiedy porszuam telefonem, śledzić pozycje placement indicator kiedy poruszamy telefonem i spawnuj object AR
    25.     void Update()
    26.     {
    27.         if (spawnedObject == null && placementPoseIsValid && Input.touchCount > 0 && //jesli nie ma zespawnowanego obiektu, i pozycja jest ok i gdy kliknieto na ekran spawnuje objekt
    28.             Input.GetTouch(0).phase == TouchPhase.Began)
    29.         {
    30.             placeARObject();
    31.         }
    32.      
    33.         UpdatePlacementPose();
    34.         UpdatePlacementIndicator();
    35.      
    36.     }
    37.  
    38.     void UpdatePlacementIndicator()
    39.     {
    40.         if (spawnedObject == null && placementPoseIsValid)
    41.         {
    42.             placementIndicator.SetActive(true); //jesli obiekt jest null czyli nie widac go, to widac wskaznik
    43.             placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);//updatowana pozycja znacznika,
    44.                                                                                                                 //position i rotation obliczone na podstawie hitu promienia z funkcji UpdatePlacementPose
    45.         }
    46.         else
    47.         {
    48.             placementIndicator.SetActive(false); //jesli jest zespawnowany obiekt to nie widac znacznika
    49.         }
    50.  
    51.     }
    52.  
    53.     void UpdatePlacementPose() //funkcja updatujaca
    54.     {
    55.         var screenCenter = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f)); //srodek ekranu
    56.         var hits = new List<ARRaycastHit>();
    57.         aRRaycastManager.Raycast(screenCenter, hits, TrackableType.Planes); //Na TrackableType.Planes rzucany jest promien ze srodka ekranu
    58.  
    59.         placementPoseIsValid = hits.Count > 0; //zmiemniam na true kiedy jest jakis hit czyli wybrano miejsce
    60.         if (placementPoseIsValid)
    61.         {
    62.             placementPose = hits[0].pose;
    63.         }
    64.     }
    65.  
    66.     void placeARObject()
    67.     {
    68.         spawnedObject = Instantiate(arObjectToSpawn, placementPose.position, placementPose.rotation); //dla spawnedObject tworzymy intsacje,
    69.                                                                                                       //do ktorej przekazujemy model, pozycje i rotacje wyzej obiczona
    70.     }
    71. }
    72.  
     

    Attached Files:

  2. FrankvHoof

    FrankvHoof

    Joined:
    Nov 3, 2014
    Posts:
    258
    The easiest way to do this is to have your user click twice. Once in the position you want to place the object, and once more to pick it's rotation (from a forward-vector). In between these two clicks you'll spawn a 'temporary' object. You can then have this temporary object rotate towards each next click (using e.g. Transform.LookAt), until the user confirms their choice.
     
    aleksos54 likes this.
  3. aleksos54

    aleksos54

    Joined:
    Jul 12, 2021
    Posts:
    4
    Thank you ! I have tried using Transform.LookAt but it didint work for me. Propalby I did something wrong. Now I am trying with object.transform.rotation but it also doesnt work.I have made 2 separate placement indicators where one is active when the object inst spawned and second when I spawn the object. Please help me to fix the code to get my object rotated after second point being placed

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.XR.ARFoundation;
    5. using UnityEngine.XR.ARSubsystems;
    6.  
    7. public class ARPlacement : MonoBehaviour
    8. {
    9.     public GameObject arObjectToSpawn;
    10.     public GameObject placementIndicator;
    11.     public GameObject placementIndicator2;
    12.  
    13.     private GameObject spawnedObject;
    14.  
    15.     private Pose placementPose;
    16.     private ARRaycastManager aRRaycastManager;
    17.     private bool placementPoseIsValid = false;
    18.     private List<ARRaycastHit> _hits = new List<ARRaycastHit>();
    19.     // Start is called before the first frame update
    20.     void Start()
    21.     {
    22.         aRRaycastManager = FindObjectOfType<ARRaycastManager>();
    23.  
    24.     }
    25.  
    26.     //update placement indicator kiedy porszuam telefonem, śledzić pozycje placement indicator kiedy poruszamy telefonem i spawnuj object AR
    27.     void Update()
    28.     {
    29.         if (spawnedObject == null && placementPoseIsValid && Input.touchCount > 0 && //jesli nie ma zespawnowanego obiektu, i pozycja jest ok i gdy kliknieto na ekran spawnuje objekt
    30.             Input.GetTouch(0).phase == TouchPhase.Began)
    31.         {
    32.             placeARObject();
    33.         }
    34.        
    35.         UpdatePlacementPose();
    36.         UpdatePlacementIndicator();
    37.  
    38.         if (spawnedObject == true)
    39.         {
    40.             UpdatePlacementPose();
    41.             UpdatePlacementIndicator_2();
    42.  
    43.             if (placementPoseIsValid && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
    44.             {
    45.                 Vector3 pos = spawnedObject.transform.position;
    46.                 Vector3 dir = (placementIndicator2.transform.position - pos).normalized;
    47.                
    48.                 //Vector3 direction = new Vector3(placementIndicator2.transform.position + spawnedObject.transform.position);
    49.                 spawnedObject.transform.rotation = Quaternion.Euler(dir);
    50.             }
    51.  
    52.             //spawnedObject.transform.rotation(direction);
    53.         }
    54.        
    55.        
    56.     }
    57.  
    58.     void UpdatePlacementIndicator()
    59.     {
    60.         if (spawnedObject == null && placementPoseIsValid)
    61.         {
    62.             placementIndicator.SetActive(true); //jesli obiekt jest null czyli nie widac go, to widac wskaznik
    63.             placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);//updatowana pozycja znacznika,
    64.                                                                                                                 //position i rotation obliczone na podstawie hitu promienia z funkcji UpdatePlacementPose
    65.         }
    66.         else
    67.         {
    68.             placementIndicator.SetActive(false); //jesli jest zespawnowany obiekt to nie widac znacznika
    69.         }
    70.  
    71.     }
    72.  
    73.     void UpdatePlacementIndicator_2()
    74.     {
    75.         if (spawnedObject == true && placementPoseIsValid)
    76.         {
    77.             placementIndicator2.SetActive(true); //jesli obiekt jest null czyli nie widac go, to widac wskaznik
    78.             placementIndicator2.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);//updatowana pozycja znacznika,
    79.             //position i rotation obliczone na podstawie hitu promienia z funkcji UpdatePlacementPose
    80.         }
    81.         else
    82.         {
    83.             placementIndicator2.SetActive(false); //jesli jest zespawnowany obiekt to nie widac znacznika
    84.         }
    85.  
    86.     }
    87.     void UpdatePlacementPose() //funkcja updatujaca
    88.     {
    89.         var screenCenter = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f)); //srodek ekranu
    90.         var hits = new List<ARRaycastHit>();
    91.         aRRaycastManager.Raycast(screenCenter, hits, TrackableType.Planes); //Na TrackableType.Planes rzucany jest promien ze srodka ekranu
    92.  
    93.         placementPoseIsValid = hits.Count > 0; //zmiemniam na true kiedy jest jakis hit czyli wybrano miejsce
    94.         if (placementPoseIsValid)
    95.         {
    96.             placementPose = hits[0].pose;
    97.         }
    98.     }
    99.  
    100.     void placeARObject()
    101.     {
    102.         spawnedObject = Instantiate(arObjectToSpawn, placementPose.position, Quaternion.identity); //dla spawnedObject tworzymy intsacje,
    103.                                                                                                       //do ktorej przekazujemy model, pozycje i rotacje wyzej obiczona
    104.     }
    105. }
     
  4. FrankvHoof

    FrankvHoof

    Joined:
    Nov 3, 2014
    Posts:
    258
    Your code seems alright for what you are trying to do, but has some small issues:

    - Don't use 'spawnedObject == true', use 'spawnedObject != null' instead to check whether an object has been spawned. Checking for 'if (spawnedObject) {}' works, but shouldn't be used with Unity Objects (convention).
    - Quaternion.Euler creates a quaternion from a rotation around the axes. The 'dir' you are putting in is a forward-direction (in worldspace), not a rotation. Thus, you will not get a valid rotation from this.

    The easiest way to implement a LookAt here is:

    Code (CSharp):
    1. void LookToPoint(GameObject spawnedObject, Vector3 point) // Point is in WorldSpace
    2. {
    3.     Transform spawnedTf = spawnedObject.transform;
    4.     // Negate 'vertical offset' to prevent SpawnedObject from looking Up/Down
    5.     Vector3 pointOnPlane = Vector3.ProjectOnPlane(point, spawnedTf.up);
    6.     // Look at point (relative point on the same plane)
    7.     spawnedTf.LookAt(pointOnPlane, spawnedTf.up);
    8. }
     
  5. mikedepetris

    mikedepetris

    Joined:
    Dec 10, 2021
    Posts:
    1
    Have you gone any forther about this?