ButtonPlus
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).
| Namespace | OxGKit.ButtonSystem |
| Type | public class ButtonPlus : UnityEngine.UI.Button |
| Source | ButtonPlus.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
- Hierarchy menu: GameObject -> UI -> Button Plus - TextMeshPro or GameObject -> UI -> Legacy -> Button Plus (scaffolds an Image and the matching text label automatically).
- 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.
- 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
| Mode | Behavior |
|---|---|
None | No long-click behavior (identical to a normal Button). |
Once | After holding for triggerTime, fires onLongClickPressed once. |
Continuous | Fires onLongClickPressed for the first time after holding for triggerTime, then keeps firing every intervalTime while held. |
PressedAndReleased | Fires 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 withTime.unscaledDeltaTimeorTime.deltaTime. - The triggerTime delay is scheduled via
MonoBehaviour.Invoke, which is affected byTime.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:
- Extd Long Click: long-click mode dropdown; per mode it shows the Ignore Time Scale, Trigger Time, Interval Time (Continuous only) fields.
- Extd Transition: extended transition dropdown; selecting Scale shows the Size field.
- Native UGUI Button block: Interactable, Transition, Navigation, On Click ().
- 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
| Member | Description |
|---|---|
| extdTransition | Extended transition mode (None / Scale). |
| transScale | Scale transition settings (scale factor). |
| extdLongClick | Long-click mode (None / Once / Continuous / PressedAndReleased). |
| ignoreTimeScale | Whether the Continuous repeat timer ignores Time.timeScale. |
| triggerTime | Long-click trigger time (seconds). |
| intervalTime | Continuous 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 thesizeof 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
| Event | Description |
|---|---|
| onLongClickPressed | Long-click pressed event (Once / Continuous / PressedAndReleased). |
| onLongClickReleased | Long-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:
| Member | Description |
|---|---|
originSize | Original size (recorded automatically in Awake from transform.localScale.x; hidden in the Inspector). |
size | Pressed 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):
| Method | Extended 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.