Currently when I am trying to detect whether an object has been clicked / interacted with by the mouse, I create a script on that GameObject and then define void OnMouseDown() and apply functionality within. If I then want to trigger a function in another script that is not attached to the GameObject I call it through a GetComponent<>() reference.
Is there a way to add a callback to the OnMouseDown event from a script on another GameObject? Potentially in the same way delegates / events are allocated and invoked? Something such as: gameObjectReference.GetComponent<BoxCollider>().onmousedownevent += MyFunction; So that it automatically calls this function on mouse down?
Note: I know that you can use raycasting to achieve something similar, but my question is about attaching callbacks to the existing Unity event.
1) I understand the sense of what you mean by this
pseudocode:
gameObjectReference.GetComponent<BoxCollider>().onmousedownevent += MyFunction
and there is no way to do that.
2) please do understand: it is incredibly easy to achieve your aim (elegantly). Add a UnityEvent in script "b", Invoke it in the OnMouseDown. drag anything you want there. For anyone reading who is new to Unity, pls try UnityEvent in general as it is used constantly
3) A I mention you can kind of do what you want by fooling around with the OnPointerDown(PointerEventData eventData) systems, but this just emphasises you can't do what you ask, do it with OnMouseDown.
Sorry for the grim news.
Related
I am working on a project with Unity and Leap Motion.
Basically, there is an inputField. In the inputField the user will write the distance, in centimeters, for which the grasp event should be triggered. When the fingers get closer than the distance of the user's input, the grasp event is triggered and a ball is grabbed. That's because I'm working with people with movement deficits and they can't fully close their hands.
I've written a script that prints the distance between the two fingers at each frame, but I don't know how to trigger the grasp event using the distance of the inputField. Any advice?
The most straightforward way to implement this is to introduce a variable which reads the content of the inputField and an if statement that triggers the event on Update() within the script you have written - something like that (assuming you're calculating graspDist as you described):
float dist = float.Parse(gameObjectWithInputField.GetComponent<InputField>().text);
if(dist/100f<graspDist) TriggerGraspEventFunction();
and then you define your TriggerGraspEventFunction() somewhere else within that script. You can either make the gameObjectWithInputField a public GameObject and drag it in in the inspector or tag it and use FindGameObjectWithTag
There are many more refined ways but this should do it for now
I want to use a single script to control all elements of one scene. Let's call it "Director" script, bound to EventSystem.
I knew that I can get a GameObject by name or tag, and then manipulated the components such as transform. Thus I wondered if I can define the OnTrigerCollider2D() in this "Director” script without binding any script to the Collider2D GameObject, just like I define the value of the transform? If possible, how?
According to some friend, it is necessary to bind at least a basic script to the Collider2D to authorize the "Director" script to get access to the Collider2D event, no way to bypass this limitation?
From the docs:
MonoBehaviour.OnTriggerEnter2D(Collider2D)
Sent when another object enters a trigger collider attached to this
object (2D physics only).
Further information about the other collider is reported in the
Collider2D parameter passed during the call.
In order for the event to fire, the trigger collider must be attached to the same object as your behavior. Using a small script on the object with the collider with a reference to call a method on your "Director" is the most common way I've seen this done. As far as I know, it's impossible for objects to "subscribe" to collision events fired by other objects.
A poster here suggests that one solution could be to create a collision manager that the "Director" checks, but the objects actually having collision events would need to notify the collision manager, so with that solution you're just adding a step. Depending on what you actually want to do with collision events, it might make sense for you though.
I attempted to give a delay to my function in Unity using C# language. By using Invoke, I achieved to add delay when the cursor is moved to a certain area. However, now I need to cancel the Invoke when the cursor is moved from that certain area. The idea is, when I accidentally move the cursor to the area, I can cancel whatever function being invoked there.
Here's my current code.
void SceneCall(){
Application.LoadLevel (MainMenu);
}
void SceneCallIn(){
Invoke ("SceneCall", 3f);
}
if (_newGameButton.Contains (Event.current.mousePosition)) {
SceneCallIn();
}
I tried to use CancelInvoke() as else, and it even doesn't want to invoke anymore when I move my cursor to _newGameButton afterwards. How do you cancel an Invoke then activate it once again? Thank you for your answer~
EDIT: Like #Programmer says in comments, what I exactly want to do is when my mouse is position at a certain point, timer will start counting. After 3 seconds
MainMenu scene will be loaded. While the timer is counting and the pointer is moved away from that certain position, I want the timer to stop and I don't want the MainMenu scene to be loaded anymore.
If you truly want to have "rollovers" and so on, here is a full tutorial:
https://stackoverflow.com/a/36046495/294884
Really you will have to become totally expert in all that, before you can do it.
I must tell you again though:
For 15 years now, you should never use rollovers for any reason in interface.
I faced the same problem yesterday, but I solved simply calling again the invoke method.
Here is my code:
public void OnGazeEnter()
{
InvokeRepeating("OnGazeStay", 0.0f, 1.0f / 30.0f);
}
public void OnGazeExit()
{
CancelInvoke("OnGazeStay");
}
In your case, if you want to register more than one method, you will have to save some sort of List<String> myMethods, so you will be able to delete every method that you've registered.
I am currently working on some Unity VR project and I have a problem with gaze functions. As an example I will use Google VR DemoScene object named Cube. There is a Teleport script attached with some gaze code at the end:
public void OnGazeEnter() {
SetGazedAt(true);
}
public void OnGazeExit() {
SetGazedAt(false);
}
public void OnGazeTrigger() {
TeleportRandomly();
}
However this fragment seems to be useless and all gaze events are handled by EventTrigger component attached to the Cube object.
My question is - how do you handle gaze events (OnGazeEnter, OnGazeExit, OnGazeTrigger) with this code only? It would be way simpler not to attach EventTrigger component all the time.
They are not useless, just not very well documented how to use it. It tooks me a while for me to figure out how to.
If you want to use them, what you need to do is remove the EvenTrigger component, then select the Main Camera and Add the component called "GVRGaze" and now these events are fired by code (OnGazeEnter, OnGazeExit, OnGazeTrigger)
You can use the mask to filter layers if you want, this is very helpful.
Hope this helps you.
How do I detect Input.GetMouseButtonUp outside a specific GameObject's area in Unity? Are there any Unity Assets for this, or should we do this programmatically?
It certainly has to be done by programming it, whether there is an asset or not. As it is rather easy to program, I doubt there is one.
What you need to understand is, that Input.GetMouseButtonUp(int button) is an event and entirely decoupled from any "position". The description from the API says "Returns true during the frame the user releases the given mouse button.".
So in the frame a mouse button has been released you want to check if the arrow is "touching" or laying over some GameObject (GO). According to your example you will do nothing when the GO was hit, and else do something.
One way to do that is to use the following method:
http://docs.unity3d.com/ScriptReference/Camera.ScreenPointToRay.html
Your GameObject will at least need a collider, maybe a rigidbody too in order to be detected by the ray. I'm not completely sure atm if both are needed.
Additional note: Having an UI element, this method could also be used to set some flag while hovering over it e.g. : http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseOver.html