Econia #1: Clicking Like a Champ

Sometimes simply clicking something isn’t enough.  Sometimes you need to click, double click, or click + hold! Here’s what we implemented when working on Econia.  Link to the full source at the bottom.

champ_click

Generally, once a click begins we start a timer to check if the player holds for long enough (in which case he is “click + hold”-ing) and after a click ends we start a timer to check if the player double clicks.

What makes things annoying is that we can’t afford to wait even a fraction of a second before an object responds to a player’s input. We can’t wait to see if he is indeed double-clicking before the player feels a response to his first click. So we end up with 5 different situations we need to handle.

  1. Click-Begins: Straight forward. We always start some visible reaction here.
  2. Click-Ends: This happens both when a player releases the input, OR when the input leaves the object.
  3. Single-Click: We fire this a fraction of a second AFTER the Click-End (if the player is still on the object), once we are satisfied the player is not double-clicking.
  4. Double-Click: This we can fire simultaneously with the second Click-End (since we don’t support triple-clicking)
  5. Click-Hold: We fire this half a second after the Click-Begins, if there hasn’t been a Click-End. We also automate a Click-End.

Interesting side note: Some mobile games such as Clash of Clans will still register a “click” even if you move your finger off of the object, so long as you move it back over the object before releasing. And only for specific objects. I’m not sure if they did this on purpose?

There are several ways we could have implemented this. The simplest is to have a “Clickable Object” script that inherits from MonoBehavior, and anything we want to use this functionality will inherit our Clickable Object script. We could also have a Clickable Object script that fires off events, and other components that need to know about them can subscribe, in case we wanted separate components to handle the response to different events, or are tripping over messy inheritance chains.

We’ll use inheritance in Econia for now, but I’ve included the source for both methods in this sample project.

ScottPlusPlus

Working to upgrade our democracy by making voting more awesome (ex: STAR Voting). Reach out if you want to chat about saving the world.

4 thoughts to “Econia #1: Clicking Like a Champ”

  1. re. “Interesting side note: Some mobile games such as Clash of Clans will still register a “click” even if you move your finger off of the object, so long as you move it back over the object before releasing. And only for specific objects. I’m not sure if they did this on purpose?”

    This is actually standard behaviour on most OSes I can think of, and hence has probably carried through to most bespoke UIs…

    Not sure whether it’s a side effect of early implementations which has carried through, but it’s definitely useful for people with motor control issues.

    1. I never actually noticed it before on my PC but now that you mention it, yeah! I’ll have to find a way to implement this as well.

      It gets annoying because the object needs to know if the player has released the mouse, even when it’s not over the object, and the best way I can think to do that is by checking every frame (once active), which is less than ideal. Maybe you have a more elegant solution?

      1. Afraid I don’t! 🙂

        I think it’s generally implemented with a “focus” widget reference.

        ie. when you click (or tab to) a button, you mark it as focused (with a flag, or a top level reference to it, or even both). You only fire click events when the mouse was released over the focused widget

        If you’re looking for real elegance though, there’s been some great stuff coming out of FRP – but that may not be appropriate for you (and has its own set of caveats): https://www.youtube.com/watch?v=XRYN2xt11Ek

        1. oh I forgot to mention:

          The benefit of having a window-level “current focus” reference is that your top-level mouse routines can easily handle cases like “release outside” rather than each widget doing it itself.

          You can use a similar thing for widget-independent hover behaviours like tweening tooltips and so forth too.

          FYI: My knowledge on this stuff is likely *way* outdated nowadays, so take grains of salt everywhere 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *