[Unity 4.6 Beta] Probing UI input objects

I’ve been trying to transition from nGUI to uGUI, but having a terrible time figuring out where my mouse over/clicks are going.

NGUI had a convenient “last hit widget” variable on their UICamera implementation that you could inspect, is there something I can check globally for uGUI?

Or should I do a manual raycast? Would a raycast even get what I’m looking for?

Thanks!

I haven’t found anything that directly returns the last control selected/clicked/submitted either.

The lame, simple workaround I’ve used is to have a component that sets the last hit game object in a static class or controller object. Attach to every control you want to register. The PointerEventData structure sent to OnPointerEnter(), OnPointerClick() etc. contains a position too. You might have to translate between screenspace and worldspace, depending on your canvas type.

If you want to try implementing a more generic solution, you might be able to do it by checking if the pointer is over a control when clicked, then raycasting, getting the first object and reading the Input.MousePosition.

I have some partial code from a script I made while implementing right-click/middle-click events:

// Important to avoid death by typing :)
using UnityEngine.EventSystems;

// This goes wherever (make it private if you like)
List<RaycastResult> results;

// Initialise the list (Awake/Start)
results = new List<RaycastResult>();

// This goes inside an Update() function on a game controller or something
if(Input.GetMouseButtonDown(0) && EventSystemManager.currentSystem.IsPointerOverEventSystemObject())
{
	PointerEventData ped = new PointerEventData(EventSystemManager.currentSystem);
	ped.position = Input.mousePosition;
	results.Clear();
	EventSystemManager.currentSystem.RaycastAll(ped, results);
	// The frontmost control is now in results[0].go
}

Slightly untested, as it was part of something else, but should probably work.

Based on Orb’s response (thanks!), I created the attached script. You can attach it at runtime if you ever get stuck trying to figure out what’s interacting with your input. Seems to be pretty helpful so far, I hope you get some use out of it.

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System;
using System.Collections.Generic;

//[RequireComponent( typeof( CRequired ) )]
public class CEventSystemProbe : MonoBehaviour
{
    public enum EConstraint
    {
        AlwaysOn,
        RightMouse
    }

    public enum EVisualization
    {
        None,
        Colorize,
        //DrawBounds        // #TODO (draw a bounding box with minimum size at top layer, 
                            //          not all objects are visible with basic colorization)
    }

    ///////////////////////////////
    /// INSPECTOR PARAMS

    public EConstraint      Constraint          = EConstraint.AlwaysOn;
    public EVisualization   Visualization       = EVisualization.None;
    public Color            VisualizationClr    = Color.red;

    [Header( "---- OUTPUT ----" )]
    [Space( 10.0f )]
    public List<GameObject> AllHitObjects       = new List<GameObject>();
    public GameObject       TopHitObject        = null;

    ///////////////////////////////

    List<RaycastResult> mRaycastResults         = new List<RaycastResult>();
    GameObject mLastObj                         = null;
    Color mLastObjClr                           = Color.white;

    public void DoRaycast()
    {
        if ( EventSystemManager.currentSystem.IsPointerOverEventSystemObject() )
        {
            PointerEventData ped = new PointerEventData( EventSystemManager.currentSystem );
            ped.position = Input.mousePosition;
            mRaycastResults.Clear();
            AllHitObjects.Clear();
            EventSystemManager.currentSystem.RaycastAll( ped, mRaycastResults );

            TopHitObject = null;
            for ( int i = 0 ; i < mRaycastResults.Count ; ++i )
            {
                if ( mRaycastResults*.isValid )*

AllHitObjects.Add( mRaycastResults*.go );*

if ( i == 0 )
TopHitObject = mRaycastResults*.go;*
}
}
}

public void UpdateVisualization()
{
if ( mLastObj != TopHitObject )
{
switch ( Visualization )
{
case EVisualization.None:
break;
case EVisualization.Colorize:
{
if ( mLastObj != null )
{
Graphic g = mLastObj.GetComponent();
if ( g != null )
g.color = mLastObjClr;
}

if ( TopHitObject != null )
{
Graphic g = TopHitObject.GetComponent();
if ( g != null )
{
mLastObjClr = g.color;
g.color = VisualizationClr;
}
}
break;
}
}

mLastObj = TopHitObject;
}
}

///////////////////////////////
/// UNITY

protected void Update()
{
switch ( Constraint )
{
case EConstraint.RightMouse:
if ( !Input.GetMouseButtonDown( 1 ) )
return;
break;
}

DoRaycast();
UpdateVisualization();
}

///////////////////////////////
}