2
\$\begingroup\$

I am trying to make a simple tooltip for my game. I added event trigger to object that I want to trigger an event on mouse hover (PointerEnter).

enter image description here

And I want to get the game object that triggered the event in ShowTooltip(). I tried requiring BaseEventData in the void but it gave me error.

void ShowTooltip(BaseEventData baseEvent)
{
    Debug.Log(baseEvent.selectedObject.name);
}

The error: Failed to call function ShowTooltip of class UIManager

Calling function ShowTooltip with no parameters but the function requires 1.

\$\endgroup\$
2
\$\begingroup\$

By default, the Event Trigger only supports method calls that take 0 or 1 parameters. Since you are invoking SendMessage() through your event, your only invoking the method SendMessage(string), as opposed to the overloaded option of SendMessage(string, object). As such, you are not able to send the required parameters through to ShowTooltip(BaseEventData), and are receiving an error because there is no ShowTooltip().

Providing reference to the calling object via Event Trigger

An easy solution I would suggest is simply creating a public tool tip method that takes an "identifier" variable, and invoking it directly, without the use of SendMessage(). If your original ShowTooltip() method does not need to be private, I would suggest just making it public, changing it, and directly triggering it from the Event Trigger. If it needs to be private, you can create an overload to call, which may still be public.

public void ShowTooltip(Object object)
{
    Debug.Log(object.name);
}

By accessing it directly, through the Event Trigger, you give yourself the allowance of providing an additional parameter. Simply drag the main object onto this field to create a contextual "self-reference".

The Event Trigger, set up to call "ShowTooltip", providing itself as a parameter.

Providing additional parameters in a method, and Overloading

It is important to understand why your original method call did not work, as it is a core mechanic in programming.

When you create a method, adding extra parameters in the signature does not automatically provide those parameters in the function. You still have to provide the parameters during the method call. If you do not provide the minimum required parameters, when you call your method, it is not going to work.

Consider the following code fragment:

void ShowTooltip(BaseEventData baseEvent)
{
    Debug.Log(baseEvent.selectedObject.name);
}

void OnMouseHover()
{
    ShowTooltip();
}

When you call OnMouseHover(), it is going to call ShowTooltip(). This causes errors, because in this context, there is no ShowTooltip(). We have a ShowTooltip(BaseEventData), but this does not match the exact method call we are using.

Ignoring the fact that fixing the error would not really solve your problem, it might be useful to understand the options you have for providing matching method calls, given the possible context. You have two options that would allow you to still call ShowTooltip(): providing default parameters, and overloading.

Default parameters

When you list parameters in a method signature, you can often provide default values. These values need to be runtime-ready; You can not use a value that is not readily available, such as deriving a value from a differant function call. In this case, we are using BaseEventData. We do not have a default value readily available, but we can default it to null.

void ShowTooltip(BaseEventData baseEvent = null)
{
    if(baseEvent != null)
    {
        Debug.Log(baseEvent.selectedObject.name);
    }
}

We can now use this method signature to call either ShowTooltip() or ShowTooltip(BaseEventData). If we do not provide a value for BaseEventData, it will default to null. It is important that you check that BaseEventData != null before using it in any way, to ensure you will not trigger null exceptions when you call this method as ShowTooltip().

Overloading

Another option you have is to simply write an additional method with the required signature.

void ShowTooltip()
{
    ...
    BaseEventData baseEvent;
    ShowTooltip(baseEvent);
}

void ShowTooltip(BaseEventData baseEvent)
{
    Debug.Log(baseEvent.selectedObject.name);
}  

This way, you provide separate functionality, depending on wether you submit BaseEventData or not. You can also call alternate methods of the same name, so you have the option of working out baseEvent in ShowTooltip(), before calling ShowTooltip(baseEvent) from within.

Overloads do not have to be of the same protection level, either. You will have no problem with public void ShowTooltip() and private void ShowTooltip(BaseEventData baseEvent). This makes it useful if you do not wish to have public access to your original method, as you can expose a 'weaker' variant for public access.

Overloading is also popular for supporting multiple formats. For example, you may wish to accept a value as either a float or an int. You could have void DoStuff(float value) and void DoStuff(int value), to manually handle either option. You cannot have differant return types, so keep that in mind, as well. float DoStuff(float value) and int DoStuff(int value will not work as I have described.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ nice explanation!! \$\endgroup\$ – Arsal Imam Feb 24 '18 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.