Author Topic: Detecting hits in NGUI  (Read 8995 times)

Excal

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 21
    • View Profile
Detecting hits in NGUI
« on: May 05, 2014, 08:44:16 PM »
I'm still new to NGUI, so please bear with me.

I have a separate scene with a basic UI set up. This scene is additively loaded into my game scene to display the UI. My game prototype is an RTS, and I use raytracing to determing when the user has clicked an object in the game. With immediate mode UI, I would have to write a function to check whether the user has clicked within the UI boundaries (a box with height 200px at the bottom of the screen). Do I do anything different with NGUI? How do I determine if the player has clicked within an NGUI element, even if that element doesn't have a click-based trigger, such as a HUD overlay?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Detecting hits in NGUI
« Reply #1 on: May 05, 2014, 11:58:11 PM »
1. Don't do your own raycasts. NGUI will do raycasts for you if you put a UICamera on the camera that sees the objects.
2. With #1 in place, UICamera.hoveredObject tells you what's underneath the mouse at any given time. It can be a UI element or a 3D object -- whatever is on top. Events will automatically go to the top-most element, so if you have a widget covering the 3D object, and the widget has a collider, it will intercept events from going to the 3D object.

Excal

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 21
    • View Profile
Re: Detecting hits in NGUI
« Reply #2 on: May 06, 2014, 12:24:38 AM »
Ah, thank you so much for the clarification. Not having to code the raycasting manually is awesome. However, I'm not sure how I should be using UICamera.hoverObject:



This shouldn't resort to null.

  1. void Update () {
  2.                 if(OurPlayer.IsHuman) {
  3.                         MouseActivity();
  4.                 }
  5.         }

MouseActivity checks for left or right mouse click. In left mouse click, which is the only action I've taken in the image above:

  1. private void LeftMouseClick() {
  2.                 Debug.Log (UICamera.hoveredObject);
  3.                 if (UICamera.hoveredObject != null)
  4.                         OurPlayer.SelectedObject = UICamera.hoveredObject.GetComponent<WorldObject>();
  5. }

But UICamera.hoveredObject always equals null no matter how many times I click the tank, which is named 'Tank'. In some older posts, I see you recommend switching entirely to NGUI's event system, but I'm not quite sure what I should be doing to grab game objects that aren't part of the UI.
« Last Edit: May 06, 2014, 01:17:59 AM by Excal »

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
Re: Detecting hits in NGUI
« Reply #3 on: May 06, 2014, 07:38:16 AM »
NGUI will give you not null, if the collider you try to hit is in the UICamera's EventMask. But generally, you'd want to have a component on object you want to hit, that has OnClick, OnPress, OnHover etc in it, which will be called automatically by the event system.

Excal

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 21
    • View Profile
Re: Detecting hits in NGUI
« Reply #4 on: May 06, 2014, 03:25:17 PM »
Do you mean OnMouseDown instead of OnClick?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Detecting hits in NGUI
« Reply #5 on: May 06, 2014, 10:00:38 PM »
No. OnMouseDown is a Unity event. OnPress / OnClick etc is an NGUI event. Check the documentation page for the UICamera. It has a list of all the events NGUI sends out.

Excal

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 21
    • View Profile
Re: Detecting hits in NGUI
« Reply #6 on: May 07, 2014, 01:31:48 AM »
Suppose the camera that is on my UI layer has a UICamera script. If I also want to be able to click game objects, should I add a UICamera script to my main camera as well? I'm having a bit of trouble wrapping my head around how to prevent a user from clicking a game object "underneath" my UI overlay.

I'm also a bit unsure as to how I should be using OnSelect (using it over OnPress since I want to support drag-select later on). I've attached a UICamera script to my Main Camera and set the Event Type to 'World'.

Each object in my game has a Unit.cs script with the following function:

  1.         void OnSelect(bool selected)
  2.         {
  3.                 if (selected)
  4.                 {
  5.                         Debug.Log (UICamera.selectedObject);
  6.                         OurPlayer.SelectedObject = UICamera.selectedObject.GetComponent<WorldObject>();
  7.                 }
  8.         }

My debug log never shows anything, however. Is there something I'm missing here?
« Last Edit: May 07, 2014, 01:41:27 AM by Excal »

Excal

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 21
    • View Profile
Re: Detecting hits in NGUI
« Reply #7 on: May 07, 2014, 06:08:41 PM »
NGUI will give you not null, if the collider you try to hit is in the UICamera's EventMask. But generally, you'd want to have a component on object you want to hit, that has OnClick, OnPress, OnHover etc in it, which will be called automatically by the event system.

This isn't working for me. Either that, or I'm not sure what I'm doing wrong. I have a UICamera script attached to my main camera, with Event Type set to 'World'. I also have a UICamera script attached to my UI camera on a separate layer called 'UI'. Every object in my game has a script called 'Unit.cs' with a void OnSelect function. Right now all that OnSelect function is print something to the debug log. However, when I click an object, nothing shows up in the console. Am I missing something here?

EDIT: Someone else has told me that I can only use the NGUI event system with NGUI widgets, and not objects in my game world. Is this true?
« Last Edit: May 08, 2014, 12:28:11 AM by Excal »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Detecting hits in NGUI
« Reply #8 on: May 08, 2014, 02:34:25 AM »
You can use it with any object that has a collider. Either 2D or 3D.

When putting a UICamera script on your main camera, be sure to use "World" event type, not "UI" (which you've done) and that the event mask includes the layer of the object you're trying to interact with.

OnSelect is sent to each object only once. Repeated clicks on the same object won't result in a new OnSelect. Clicking away will get OnSelect(false) before the new object gets OnSelect(true).

P.S. Character inventory example has the 3D character respond to events using this method. Drag & drop example does too with the cube.

Excal

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 21
    • View Profile
Re: Detecting hits in NGUI
« Reply #9 on: May 08, 2014, 06:58:35 AM »
I think I've finally figured out what's up, but I still need some help getting things right.

It turns out my UICamera events are firing from my UI camera and not my main camera. How do I change it so that the UICamera events fire from my main camera, which has Event Type set to World and Culling Mask = Everything, instead of my Camera that's on my UI layer?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Detecting hits in NGUI
« Reply #10 on: May 09, 2014, 05:06:52 AM »
Make sure that each layer can only be seen by one camera, not both (adjust the culling mask).

Excal

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 21
    • View Profile
Re: Detecting hits in NGUI
« Reply #11 on: May 09, 2014, 06:01:19 AM »
I adjusted both culling masks. My main camera can see everything but the UI, while my UI camera can only see the UI. I'm still not getting any hits unless I enable the UI camera to see everything, and then I am only getting OnSelect() returns from objects seen by this camera.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Detecting hits in NGUI
« Reply #12 on: May 09, 2014, 06:16:23 AM »
Well, did you actually attach UICamera to the main camera as well? Events won't work without it.

Excal

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 21
    • View Profile
Re: Detecting hits in NGUI
« Reply #13 on: May 09, 2014, 06:23:30 AM »
Yes, the problem is that both cameras have UICamera script attached, but it seems like both cameras have to be seeing something for OnSelect() to fire.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Detecting hits in NGUI
« Reply #14 on: May 09, 2014, 06:43:03 AM »
Both have to be seeing something? Not sure what you mean. You can try attaching this script to a plain game object for debugging:
  1. using UnityEngine;
  2.  
  3. public class Test : MonoBehaviour
  4. {
  5.     void Start()
  6.     {
  7.         UICamera.genericEventHandler = gameObject;
  8.     }
  9.  
  10.     void OnSelect (bool isSelected)
  11.     {
  12.         if (isSelected) Debug.Log("Selected " + UICamera.selectedObject.name);
  13.         else Debug.Log("Deselected");
  14.     }
  15. }