Hi,
I’m trying to make a selection by click system which can Mixe UI and no UI element.
the first problem I solved was to know when a gameObject is “unclicked” by clicking somewhere else.
I did it this way.
1 - A Click Manager script which centralized the click input detection.
{
public delegate void RightClickDelegate();
public RightClickDelegate OnRightClick;
public delegate void LeftClickDelegate();
public LeftClickDelegate OnLeftClick;
private void Update()
{
//click gauche
if (Input.GetMouseButton(0))
{
OnLeftClick?.Invoke();
}
//click droit
if (Input.GetMouseButton(1))
{
OnRightClick?.Invoke();
}
}
}
Then a ClickMe script attached to gameObject than can be click.
public class ClickOnMe : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
[SerializeField] bool isUI = false;
[SerializeField] public List<MonoBehaviour> RightClickScripts;
public delegate void OnRightClickDelegate(bool trigger);
public OnRightClickDelegate ListenThisOnRightClick;
[SerializeField] public List<MonoBehaviour> LeftClickScripts;
public delegate void OnLeftClickDelegate(bool trigger);
public OnLeftClickDelegate ListenThisOnLeftClick;
[SerializeField] public List<MonoBehaviour> OnMouseOverScripts;
public delegate void OnMouseEnterDelegate();
public OnMouseEnterDelegate ListenThisOnMouseEnter;
public delegate void OnMouseExitDelegate();
public OnMouseExitDelegate ListenThisOnMouseExit;
bool RightClick = false;
bool LeftClick = false;
bool MouseOver = false;
private ClickManager clickManager;
private void OnEnable()
{
clickManager = FindObjectOfType<ClickManager>();
if (clickManager != null)
{
clickManager.OnRightClick += RightClickMethode;
clickManager.OnLeftClick += LeftClickMethode;
}
}
private void OnDisable()
{
if (clickManager != null)
{
clickManager.OnRightClick -= RightClickMethode;
clickManager.OnLeftClick -= LeftClickMethode;
}
}
public void RightClickMethode()
{
if (MouseOver)
{
EnableRightClickScripts(true);
RightClick = true;
Debug.Log("click on me : " + this.name + " right click");
}
else
{
EnableRightClickScripts(false);
RightClick = false;
}
if (!isUI)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity, this.gameObject.layer))
{
if (hit.transform == this.gameObject.transform)
{
EnableRightClickScripts(true);
RightClick = true;
Debug.Log("click on me : " + this.name + " Right click");
}
else
{
EnableRightClickScripts(false);
RightClick = false;
}
}
}
ListenThisOnRightClick?.Invoke(RightClick);
}
public void LeftClickMethode()
{
if (MouseOver)
{
EnableLeftClickScripts(true);
LeftClick = true;
Debug.Log("click on me : " + this.name + " left click");
}
else
{
EnableLeftClickScripts(false);
LeftClick = false;
}
if (!isUI)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * 100, Color.green, 2f);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity,this.gameObject.layer))
{
if (hit.transform == this.gameObject.transform)
{
EnableLeftClickScripts(true);
LeftClick = true;
Debug.Log("click on me : " + this.name + " left click");
}
else
{
EnableLeftClickScripts(false);
LeftClick = false;
}
}
}
ListenThisOnLeftClick?.Invoke(LeftClick);
}
public void EnableRightClickScripts(bool trigger)
{
foreach (MonoBehaviour script in RightClickScripts)
{
script.enabled = trigger;
}
}
public void EnableLeftClickScripts(bool trigger)
{
foreach (MonoBehaviour script in LeftClickScripts)
{
script.enabled = trigger;
}
}
public void OnPointerEnter(PointerEventData data)
{
MouseOver = true;
Debug.Log(this.transform.name);
Debug.Log("Mouse Enter");
foreach (MonoBehaviour script in OnMouseOverScripts)
{
script.enabled = true;
}
ListenThisOnMouseEnter?.Invoke();
}
public void OnPointerExit(PointerEventData data)
{
MouseOver = false;
Debug.Log(this.transform.name);
Debug.Log("Mouse Exit");
foreach (MonoBehaviour script in OnMouseOverScripts)
{
bool MustBeDesable = true;
if (LeftClick)
{
foreach (MonoBehaviour script2 in LeftClickScripts)
{
if (script == script2)
{
MustBeDesable = false;
break;
}
}
}
if(RightClick)
{
foreach (MonoBehaviour script3 in RightClickScripts)
{
if (script == script3)
{
MustBeDesable = false;
break;
}
}
}
if (MustBeDesable)
{
script.enabled = false;
}
}
ListenThisOnMouseExit?.Invoke();
}
}
It work fine for UI Element but fo GameObject like monster in the scene it doesn’t work.
First problem the raycast doesn’t Hit my monster.
In the scene we can clearly see that the line is passing thru the monster.
PS: in the image not anymore because of the time to me to click on pause
When I check the hit it seem to hit nothing :
Second question, what could be a good may to check if the mouse is over for non UI elements?
Don’t want to Raycast at every frame and don’t know if OnPointerEnter / Exit wiil work on non UI elements :/.
For the monster there is a lot of component attached. There is alot of script, a animator, a RigidBody and a character Controller.
I also tryed to add different colldier with trigger check or not and nothing worked
Thanks for your help, it seems I’m stuck for now.