Skip to main content

ButtonPlus

Important Attention Reminder

Coding Style wiki


ButtonPlus is a button component extended from Unity UGUI's Button (by inheritance) that fully keeps Button's original features (onClick, interactable, Transition, Navigation, etc.) and adds various Long Click behavior modes (Once, Continuous, PressedAndReleased) plus a Scale press-transition effect; create it directly from the GameObject -> UI menu, or attach it via Add Component (menu path OxGKit -> ButtonSystem -> Button -> ButtonPlus).

NamespaceOxGKit.ButtonSystem
Typepublic class ButtonPlus : UnityEngine.UI.Button
SourceButtonPlus.cs
using OxGKit.ButtonSystem;

Quick Start

using OxGKit.ButtonSystem;
using UnityEngine;

public class ControlPanel : MonoBehaviour
{
public ButtonPlus button;

private void Awake()
{
// Normal click (inherited from Button)
this.button.onClick.AddListener(() => Debug.Log("Click"));

// Switch the long-click mode and subscribe to the long-click events
this.button.extdLongClick = ButtonPlus.ExtdLongClick.PressedAndReleased;
this.button.triggerTime = 1f;
this.button.onLongClickPressed.AddListener(() => Debug.Log("Long Click Pressed"));
this.button.onLongClickReleased.AddListener(() => Debug.Log("Long Click Released"));
}
}

General Rules

Creation

  1. Hierarchy menu: GameObject -> UI -> Button Plus - TextMeshPro or GameObject -> UI -> Legacy -> Button Plus (scaffolds an Image and the matching text label automatically).
  2. Add Component: menu path OxGKit -> ButtonSystem -> Button -> ButtonPlus; to replace an existing Button, remove the Button component, attach ButtonPlus instead, and re-wire the events.
  3. Attaching from code: gameObject.AddComponent<ButtonPlus>(); you can also import the ButtonPlus Demo Sample for a complete example (see Module Intro).

Attention The overridden Awake of ButtonPlus only records the original scale size and does not call base.Awake(); when attaching from code and relying on UGUI Transition visuals, assign targetGraphic yourself.

Long Click Modes

ModeBehavior
NoneNo long-click behavior (identical to a normal Button).
OnceAfter holding for triggerTime, fires onLongClickPressed once.
ContinuousFires onLongClickPressed for the first time after holding for triggerTime, then keeps firing every intervalTime while held.
PressedAndReleasedFires onLongClickPressed after holding for triggerTime; fires onLongClickReleased on release (Pointer Up) or when the pointer leaves the button (Pointer Exit).

Attention Long click and click are mutually exclusive: in any long-click mode, once a long click has triggered, that release will not fire onClick (the component temporarily swaps the onClick event out to avoid an accidental invoke) — a single press is either a click or a long click.

Attention PressedAndReleased also fires onLongClickReleased when the pointer leaves the button, so handlers must tolerate a release without the pointer returning onto the button.

Timing Rules

  • ignoreTimeScale (default true) decides whether the Continuous repeat timer accumulates with Time.unscaledDeltaTime or Time.deltaTime.
  • The triggerTime delay is scheduled via MonoBehaviour.Invoke, which is affected by Time.timeScale (regardless of ignoreTimeScale).

Important While the game is paused (Time.timeScale = 0), the initial long-click trigger (triggerTime) does not happen; ignoreTimeScale only guarantees that the Continuous repeat interval after triggering is unaffected by time scaling.

Inspector Layout

The custom Inspector, from top to bottom:

  1. Extd Long Click: long-click mode dropdown; per mode it shows the Ignore Time Scale, Trigger Time, Interval Time (Continuous only) fields.
  2. Extd Transition: extended transition dropdown; selecting Scale shows the Size field.
  3. Native UGUI Button block: Interactable, Transition, Navigation, On Click ().
  4. Long-click event slots (shown when the mode is not None): On Long Click Pressed (); the PressedAndReleased mode additionally shows On Long Click Released ().

Reminder The Scale transition composes with the native UGUI Transition (Color Tint, etc.); avoid overwriting designer-authored transition settings from runtime code.


Extended Settings

Members Overview

MemberDescription
extdTransitionExtended transition mode (None / Scale).
transScaleScale transition settings (scale factor).
extdLongClickLong-click mode (None / Once / Continuous / PressedAndReleased).
ignoreTimeScaleWhether the Continuous repeat timer ignores Time.timeScale.
triggerTimeLong-click trigger time (seconds).
intervalTimeContinuous repeat interval time (seconds).

extdTransition

public ExtdTransition extdTransition = ExtdTransition.None

Extended transition mode (Inspector: Extd Transition), see ExtdTransition:

  • None: no extended transition.
  • Scale: scales the button uniformly by the size of transScale while pressed, and restores the original size when the click completes or the pointer exits (also reset on component disable/destroy).

transScale

public TransScale transScale = new TransScale()

Scale transition settings (TransScale); size is the pressed scale factor (default 0.95, Inspector: Size).

button.extdTransition = ButtonPlus.ExtdTransition.Scale;
button.transScale.size = 0.9f; // Shrink to 90% while pressed

Attention The original size is recorded in Awake from transform.localScale.x, and scaling/restoring is applied uniformly (same value on XYZ) — buttons with a non-uniform scale are not suitable.

extdLongClick

public ExtdLongClick extdLongClick = ExtdLongClick.None

Long-click mode (Inspector: Extd Long Click), see Long Click Modes and ExtdLongClick.

ignoreTimeScale

public bool ignoreTimeScale = true

Whether the Continuous repeat timer ignores Time.timeScale (default true, accumulating with Time.unscaledDeltaTime); when set to false it uses Time.deltaTime instead, so the repeat interval scales with game time — see Timing Rules.

triggerTime

public float triggerTime = 1f

Long-click trigger time (seconds, default 1, Inspector: Trigger Time); holding past this time triggers the long click (applies to Once / Continuous / PressedAndReleased).

intervalTime

public float intervalTime = 0.1f

Repeat interval time for the Continuous mode (seconds, default 0.1, Inspector: Interval Time); after the long click triggers, onLongClickPressed fires once per interval while held.


Long Click Events

Events Overview

EventDescription
onLongClickPressedLong-click pressed event (Once / Continuous / PressedAndReleased).
onLongClickReleasedLong-click released event (PressedAndReleased only).

Both events are of the ButtonClickedEvent type inherited from Button (a UnityEvent) — same as onClick, they can be assigned in the Inspector event slots or managed with AddListener / RemoveListener / RemoveAllListeners.


onLongClickPressed

public ButtonClickedEvent onLongClickPressed { get; set; }

Long-click pressed event (Inspector: On Long Click Pressed ()):

  • Once: fires once after holding for triggerTime.
  • Continuous: after the first fire, keeps firing every intervalTime while held.
  • PressedAndReleased: fires once after holding for triggerTime.
// Hold-to-repeat (e.g. +1 every 0.1s while held)
button.extdLongClick = ButtonPlus.ExtdLongClick.Continuous;
button.triggerTime = 0.5f;
button.intervalTime = 0.1f;
button.onLongClickPressed.AddListener(this.OnIncrease);

onLongClickReleased

public ButtonClickedEvent onLongClickReleased { get; set; }

Long-click released event (Inspector: On Long Click Released ()), used by the PressedAndReleased mode only; after the long click has triggered, it fires on release (Pointer Up) or when the pointer leaves the button (Pointer Exit).

// Hold-to-preview (show while held, hide on release)
button.extdLongClick = ButtonPlus.ExtdLongClick.PressedAndReleased;
button.onLongClickPressed.AddListener(this.OnShowPreview);
button.onLongClickReleased.AddListener(this.OnHidePreview);

Reminder Register listeners once during the bind phase (ButtonClickedEvent accumulates duplicate registrations); for pooled or persistent UI, remember to clean up with RemoveAllListeners on release/destroy.


Type Definitions

ExtdTransition

public enum ExtdTransition
{
None,
Scale
}

Extended transition mode enum.

ExtdLongClick

public enum ExtdLongClick
{
None,
Once,
Continuous,
PressedAndReleased
}

Long-click mode enum, see Long Click Modes.

TransScale

[Serializable]
public class TransScale
{
[HideInInspector]
public float originSize;
public float size = 0.95f;
}

Scale transition settings:

MemberDescription
originSizeOriginal size (recorded automatically in Awake from transform.localScale.x; hidden in the Inspector).
sizePressed scale factor (default 0.95, Inspector: Size).

Pointer Event Overrides

ButtonPlus overrides the following UGUI pointer events to implement the extended behaviors (called automatically by the EventSystem — normally there is no need to call them yourself; the extended behaviors are skipped while interactable is false):

MethodExtended Behavior
public override void OnPointerDown(PointerEventData eventData)Applies the Scale transition; schedules the long-click trigger by triggerTime.
public override void OnPointerUp(PointerEventData eventData)PressedAndReleased: fires onLongClickReleased if the long click has triggered.
public override void OnPointerClick(PointerEventData eventData)Suppresses onClick if the long click has triggered; then resets the long-click state and the transition.
public override void OnPointerExit(PointerEventData eventData)Pointer leaves while held: PressedAndReleased fires onLongClickReleased; then resets the long-click state and the transition.

There are also protected helpers available for subclassing: ResetExtdLongClick() (cancels the long-click scheduling and timer), ResetExtdTransition() (restores the original size), and OnLongClick() (the long-click trigger entry); the component automatically resets the long-click state and the transition in OnDisable / OnDestroy.

Attention When subclassing ButtonPlus and overriding the pointer events above, remember to call the base versions — otherwise the long-click and transition behaviors will stop working.