1

I am building an app using arfoundation to place objects on the ground plane. I built a placement indicator for this purpose, but the issue I am facing is it is being generated for the first time, but the indicator is not moving along with my camera. Could someone please help me out. Providing my code below. I have tested this using android only.

I have also created a function to place objects on tap, which is also not working

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

public class ArTapToPlace : MonoBehaviour
{
    public GameObject objectToPlace;
    public GameObject placementIndicator;

    private ARSessionOrigin arOrigin;
    private Pose placementPose;
    private bool placementPoseIsValid = false;

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

    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()
    {
        print(placementIndicator);
        if (placementPoseIsValid)
        {
            placementIndicator.SetActive(true);
            placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);
        }
        else
        {
            placementIndicator.SetActive(false);
        }
    }

    private void UpdatePlacementPose()
    {
        var screenCenter = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
        var hits = new List<ARRaycastHit>();
        arOrigin.GetComponent<ARRaycastManager>().Raycast(screenCenter, hits, UnityEngine.XR.ARSubsystems.TrackableType.Planes);
        print(hits.Count);
        print(hits);


        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);
        }
    }
}
derHugo
  • 83,094
  • 9
  • 75
  • 115
Jerin Cherian
  • 436
  • 1
  • 5
  • 22
  • id guess its overwritten each frame with updateplacementindicator that set the location to placementpose.position and doesnt seem to be updated to any newer values.. if you want it to stay relative why not just parent it. – BugFinder Nov 06 '19 at 09:42
  • Do you see your placementIndicator GameObject moving at all? – Milos Romanic Nov 06 '19 at 09:42

1 Answers1

0

This might be related to the line

var cameraForward = Camera.current.transform.forward;

Camera.current is (almost) only used for postprocessing and only set during the rendering:

Most of the time you will want to use Camera.main instead. Use this function only when implementing one of the following events: MonoBehaviour.OnRenderImage, OnPreRender, OnPostRender.

So you rather want to use the Camera.main which is the current main camera of your scene.

var cameraForward = Camera.main.transform.forward;

In general this call is quite expensive so you should store it on app start and reuse the reference

This property uses FindGameObjectsWithTag internally and doesn't cache the result. It is advised to cache the return value of Camera.main if it is used multiple times per frame.

and I would extend the docs to "... if it is used multiple times."

// If possible already reference it via the Inspector
[SerializeField] private Camera _camera;

private void Awake()
{
    // otherwise get it once on runtime
    if(!_camera) _camera = Camera.main;
}

...

var cameraForward = _camera.transform.forward;
derHugo
  • 83,094
  • 9
  • 75
  • 115