1

I'm working on an Android application in Unity3D where I'm trying to Instantiate and Destroy GameObjects at runtime in unity3d. I'm new in unity and currently working on google's project tango where I'm just trying to place an object to the plane and then perform rotate or move operations on that GameObject with touch.

I'm using FBX files for my 3D objects and making use of event system to get the touch updates. Finding plane and placing the object to the plane is done since they have a clear tutorial available on their docs. But now I want to get the selected GameObject with touch.

I've created prefab for the imported fbx object and added a Box Collider to it. Then I've added a Physics Raycater to my Tango Camera and created an EventSystem GameObject to get touch events at runtime. See attached images.

GameObject

EventSystem

My script is this (See IsPointerOverGameObject method) :-

 using UnityEngine;
 using System.Collections;
 using UnityEngine.EventSystems;
 public class KittyUIController : MonoBehaviour
 {
 public GameObject m_object;
 private TangoPointCloud m_pointCloud;
 private bool isGameObjectSelected = false;
 void Start()
 {
     m_pointCloud = FindObjectOfType<TangoPointCloud>();
     InventoryItemDisplay.onClick += InventoryItemDisplay_onClick;
 }
 void OnDestroy()
 {
     Debug.Log ("MY LOGS - Unsigned-up for onClick");
     InventoryItemDisplay.onClick -= InventoryItemDisplay_onClick;
 }
 void Update ()
 {
     if (Input.touchCount == 1)
     {
         Touch t = Input.GetTouch(0);
         // Trigger place kitten function when single touch ended.
         if (t.phase == TouchPhase.Ended) {
             if (m_object != null && !isGameObjectSelected) {
                 Debug.Log ("MY LOGS - Placing object to the plane");
                 PlaceObject (t.position);
             } else {
                 isGameObjectSelected = false;
             }
         } else if (t.phase == TouchPhase.Began) {
             IsPointerOverGameObject (t.fingerId);    // Here i'm checking weather a GameObject is Touched or not
         }
     }
 }
 /*
 * This method will check whether a game object is touched or not using Event System    
 */
 void IsPointerOverGameObject( int fingerId){

     if (EventSystem.current.IsPointerOverGameObject (fingerId)) {
         isGameObjectSelected = true;
         Debug.Log ("MY LOGS - Is pointing over game object");
         //-------HERE IS THE REAL ISSUE-------//
         Debug.Log ("MY LOGS - GETTING SELECTED GAMEOBJECT : " + EventSystem.current.currentSelectedGameObject);
         GameObject go = EventSystem.current.currentSelectedGameObject;
         Debug.Log ("MY LOGS - Got the game object!!\nTag for game object is : "+go.tag);
         // Destroy if Object is of type 3D object
         if (go.tag == "3DObject") {
             Debug.Log ("MY LOGS - yoo a 3d object is selected");
             Destroy (go);
         } else {
             Debug.Log ("MY LOGS - Oops the selected object don't have a tag of 3d object");
         }
     } else {
         Debug.Log ("MY LOGS - Is not pointing over game object");
     }
 }
 //-------Click listener to listen to the clicks in Side Panel
 void InventoryItemDisplay_onClick (InventoryItem item, GameObject itemObject)
 {
     Debug.Log ("MY LOGS - Vola..You have selected " + item.displayName);
     m_object = itemObject;
 }
 /*
 * This method will place selected gameobject to the plane    
 */
 void PlaceObject(Vector2 touchPosition)
 {
     // Find the plane.
     Camera cam = Camera.main;
     Vector3 planeCenter;
     Plane plane;
     if (!m_pointCloud.FindPlane(cam, touchPosition, out planeCenter, out plane))
     {
         Debug.Log("MY LOGS - cannot find plane.");
         return;
     }
     // Place object on the surface, and make it always face the camera.
     if (Vector3.Angle(plane.normal, Vector3.up) < 30.0f)
     {
         Vector3 up = plane.normal;
         Vector3 right = Vector3.Cross(plane.normal, cam.transform.forward).normalized;
         Vector3 forward = Vector3.Cross(right, plane.normal).normalized;
         Instantiate(m_object, planeCenter, Quaternion.LookRotation(forward, up));
     }
     else
     {
         Debug.Log("MY LOGS - surface is too steep for kitten to stand on.");
     }
    }
 }

I have a Side Panel prefab with list items which is also getting created at runtime. So when I touches the list item at side panel to select an object everything in IsPointerOverGameObject method runs well except printing the tag of the selected object. But when I touches my object placed on the surface of the screen then it doesn't works after Debug.Log ("MY LOGS - Is pointing over game object"); in IsPointerOverGameObject method

It will get clear after seeing my logcat.

Logcat

 06-10 15:33:31.094: I/Unity(15009): MY LOGS - Is not pointing over game object
 06-10 15:33:38.619: I/Unity(15009): MY LOGS - Is pointing over game object
 06-10 15:33:38.621: I/Unity(15009): MY LOGS - GETTING SELECTED GAMEOBJECT :  InventoryItemDisplay(Clone) (UnityEngine.GameObject)
 06-10 15:33:38.621: I/Unity(15009): MY LOGS - Got the game object!!
 06-10 15:33:38.622: I/Unity(15009): MY LOGS - Oops the selected object don't have a tag of 3d object
 06-10 15:33:38.665: I/Unity(15009): MY LOGS - Vola..You have selected Rose
 06-10 15:33:45.175: I/Unity(15009): MY LOGS - Is not pointing over game object
 06-10 15:33:45.286: I/Unity(15009): MY LOGS - Placing object to the plane
 06-10 15:33:50.379: I/Unity(15009): MY LOGS - Is pointing over game object
 06-10 15:33:50.379: I/Unity(15009): MY LOGS - GETTING SELECTED GAMEOBJECT : 
 06-10 15:33:54.558: I/Unity(15009): MY LOGS - Is not pointing over game object
 06-10 15:33:54.686: I/Unity(15009): MY LOGS - Placing object to the plane
 06-10 15:33:54.688: I/Unity(15009): MY LOGS - surface is too steep for kitten to stand on.

Now, if you see the third line of the Logcat you will see that it prints the Object that is selected : InventoryItemDisplay(Clone) but in the next line if you check the Debug.Log() in code then you'll see that i doesn't prints the log after \n.... This is when I click on the item placed on side panel. Now see fourth line from the bottom of logcat. This is when I click on the Initialised gameobject. It doesn't even prints anything after that line. It directly prints out the code written in Touch.Ended condition.

ADDING SCREENSHOT FOR THE SCENE screenshot of the scene

Tarun Chauhan
  • 71
  • 1
  • 9
  • 1
    You were almost close. `Physics Raycater` goes with `EventSystems` such as `IPointerDownHandler, IPointerClickHandler, IPointerUpHandler, IPointerExitHandler, IPointerEnterHandler, IBeginDragHandler, IDragHandler, IEndDragHandler`. See the duplicated question for more info. – Programmer Jun 12 '17 at 17:43
  • Thanks a lot..i'll give it a try and let you know the outcome :) – Tarun Chauhan Jun 14 '17 at 12:50

1 Answers1

0

To the best of my knowledge, EventSystem.current.currentSelectedGameObject can only refer to a UI object, even though it is not explicitly specified in the documentation. What you are instantiating is not a UI object, but just a regular GameObject in the Scene. I cannot see the full Inspector view, but I can see that you are not setting a Transform of a Canvas as the GameObject's parent during the instantiation, and that's enough.

If you want to have a reference to the GameObject in the Scene, you would need to either store a reference to it during the instantiation, or you would need to do a Raycast based on the position of the touch to get it. The method depends on what you want to achieve.

Kasperi
  • 93
  • 1
  • 12
  • Okay...from your answer what i'm getting is i should not be able to get the gameobject that i'm instantiating. But when i touches my gameobject that i've instantiated i gets true. See logcat above. I gets true from `isPointingOverGameObject`. So i'm sure its detecting the gameobject. But only problem here is that i'm not able to get the object in order to perform certain actions with that. There is also a second possibility that i'm able to get from your answer. Are you saying that i need to instantiate the gameobject inside a canvas or something so that i could get that object's instance?? – Tarun Chauhan Jun 12 '17 at 09:37
  • 1
    Yes, I don't think it can be accessed through `EventSystem.current.currentSelectedGameObject` unless it's a UI object. I assume that "InventoryItemDisplay(Clone)" is a UI object? That would explain why you can see it in the log, but not the one you're instantiating later. And regarding your edit, `EventSystem.current.IsPointerOverGameObject(fingerId)` can also return true if there is a UI object behind the GameObject you are instantiating. I am not sure because there is no images of what actually happens during runtime so I don't know what other kind of objects there are in the Scene. – Kasperi Jun 12 '17 at 09:42
  • I've added the screenshot of the view so that you could see what's going wrong. There is no other gameobject on the screen except that kitty sitting on the floor. I'm getting true value when i touches the kitty but i'm not able to get the kitty gameobject as you can see in the log. Its not proceeding further in code when i tries to get the current selected gameobject using `EventSystem.current.currentSelectedGameObject`. – Tarun Chauhan Jun 12 '17 at 11:28
  • I am sure you already had a look at it, but the EventSystem API referred to in the duplicate is definitely the answer here. Just wanted to add it as an extension of my answer, in case anybody takes a look at it. – Kasperi Jun 12 '17 at 22:11
  • I'll definitely give it a try and update for the same ^_^ – Tarun Chauhan Jun 14 '17 at 12:50