Search Issue Tracker

Fixed in 2017.3.0f3

Fixed in 2017.1.X, 2017.2.X

Votes

5

Found in

2017.2.0b11

Issue ID

950588

Regression

Yes

OnClick event of the Button is called as many times as there are different events registered to it

uGUI

-

To reproduce:

1. Open the project, attached by the user (Click.zip)
2. Open "sample" scene
3. Enter Play mode
4. Press the button on the screen
5. Observe the console

Expected: the event on the Button is called once

Reproduced in 2017.1.1p2, 2017.2.0b11, 2017.3.0a7
Did not reproduce in 5.5.4p2, 5.6.3p3, 2017.1.1p1
Regression introduce in 2017.1.1p2

Reproduced on Windows 10

Fixed in 2017.3.0b3

Comments (20)

  1. m4ko

    Nov 28, 2017 13:15

    So... we have had a couple new releases since september. Any news on a non-2017.3.X version fix? Anyone working with unity ui can not upgrade AT ALL since 2017.1.1p1 (last version without the bug).

    "Fixed in 2017.3.0b3" doesn't help us at all.

  2. jvetulani

    Nov 22, 2017 20:43

    This is also happening in Unity 2017.30b1 on Linux.

  3. Pixel24

    Nov 16, 2017 15:47

    Is there a fix for this? I updated to Unity 2017.3b9 and this issue is back!

  4. justdizzy

    Oct 31, 2017 18:48

    (Removing foot from mouth) I just tried using 2017.1.2p2, and at least in the Editor it seems fixed for me.

  5. justdizzy

    Oct 31, 2017 18:15

    sigh... one of the (few) reasons I wish I'd stayed with open-source Cocos2d-x; if a bug was found, even if the official build wouldn't include it for a while, I could always fix the code directly in my project.

  6. aliak

    Oct 29, 2017 22:03

    Oh, Unity just stop it!!! So tired of stupid bugs that cost me a weekend!
    It happens to me when onClick has a callback with bool paramenter.

  7. odysoftware

    Oct 13, 2017 12:42

    Yeah I am curious too. Its interesting that the priority is 2 (must be fixed in next final release). But they haven't done so in 2017.1.1f and even not now in 2017.2... I mean 2017.3 seems to be months ahead - they need to backport it ??

  8. Seb-1814

    Oct 13, 2017 11:54

    Will this fix be backported to 2017.1 or 2017.2 ?

  9. jeremyburgesspp

    Oct 03, 2017 22:02

    Hi all who are watching - just thought people suffering from this bug might want to be aware that there's a [dirty] workaround you can apply. The issue in question is that the implementing generically parameterised UnityEvent Invoke methods have a bug in how they iterate their invokable calls (you can see it in the disassembly). A simple way to work around this is to forceably invoke the Invoke method on UnityEventBase passing through the array of args correctly using reflection.

    What we did is create an extension method for UnityEvent (but in your case you may need to create equivalents for, for instance UnityEvent<T0, T1> etc...) which does just that (see below). We then subclassed Button, and wholesale replaced all references to Unity UI buttons to ours, by just find/replacing the relevant script reference in all prefab/scene files. How our button's OnClick is shown below.

    Note that as the bug is in the UnityEvent types this may or may not be a workable solution for you, and will manifest for all types which make use of UnityEvent (for instance Toggles) - we just only had buttons that we needed to solve.

    Extension method:
    private static object[] s_unityEventEmptyObjectArray = new object[1]{new object[0]};
    private static MethodInfo s_unityEventInvokeMethod = null;

    public static void SafeInvoke(this UnityEvent unityEvent)
    {
    if (s_unityEventInvokeMethod == null)
    {
    s_unityEventInvokeMethod = unityEvent.GetType().BaseType.GetMethod("Invoke",
    BindingFlags.NonPublic | BindingFlags.Instance,
    null,
    new System.Type[]{typeof(UnityEngine.Object[])},
    null);
    }

    s_unityEventInvokeMethod.Invoke(unityEvent, s_unityEventEmptyObjectArray);
    }

    Button OnClick method:
    public override void OnPointerClick(UnityEngine.EventSystems.PointerEventData eventData)
    {
    // Don't call base class as onClick.Invoke() calls each thing multiple times

    // Early outs...
    if (!IsActive () || !IsInteractable ())
    {
    return;
    }

    if (eventData.button != UnityEngine.EventSystems.PointerEventData.InputButton.Left)
    {
    return;
    }

    // Use our magic method.
    onClick.SafeInvoke();
    }

  10. Guilherme-Otranto

    Oct 03, 2017 16:40

    Worth mentioning, it is not just onclick.
    I created a simple ExecuteEvent script, which is called by the button.
    My hope was to migrate the event to this script and call it from the button. No luck.

    So, the "Workaround is possible" is true, but it is a much messier solution than what I initially imagined.

Add comment

Log in to post comment

All about bugs

View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.