跳至主要内容

VirtualJoystick

重要 注意 提醒

Coding Style wiki


VirtualJoystickUGUI 虛擬搖桿組件 (MonoBehaviour),實作 UGUI 事件介面 (IPointerDownHandlerIPointerUpHandlerIDragHandler),將觸控 / 滑鼠拖曳轉換為 Vector2 搖桿向量,並透過 onStickInput 回調輸出;支持 Fixed / Floating 顯示類型、Normalized / Delta 向量模式、軸向限制死區過濾 (調整自 annulusgames - EnhancedOnScreenStick)。

命名空間OxGKit.VirtualJoystick
類型public class VirtualJoystick : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
原始碼VirtualJoystick.cs
using OxGKit.VirtualJoystick;

注意 組件標註 [AddComponentMenu("OxGKit/VirtualJoystick/VirtualJoystick")][RequireComponent(typeof(RectTransform), typeof(Image))]掛載物件本身即為觸控區域 (Image 可設為透明作為觸控感應面)。

快速上手

using OxGKit.VirtualJoystick;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
[SerializeField]
private VirtualJoystick _joystick;

private Vector2 _move;

private void Awake()
{
// 配置搖桿 (亦可直接於 Inspector 配置)
this._joystick.stickType = StickType.Floating;
this._joystick.stickVectorMode = StickVectorMode.Normalized;
this._joystick.axisConstraint = AxisConstraint.Both;
this._joystick.deadZone = 0.1f;

// 訂閱搖桿輸出回調 (放開時會收到 Vector2.zero)
this._joystick.onStickInput += this._OnStickInput;
}

private void _OnStickInput(Vector2 v2)
{
this._move = v2;
}

private void OnDestroy()
{
// 物件銷毀時取消訂閱
this._joystick.onStickInput -= this._OnStickInput;
}
}

通用規則

環境需求

  1. 組件必須位於 Canvas 之下:Awake 會取得父層 Canvas (用於解析比例與位置換算),找不到會報錯並自我停用 (enabled = false)。
  2. 場景中需有 EventSystem,且組件上的 Image 需可接收 Raycast (未被 CanvasGroup.blocksRaycasts = false 等阻擋),否則收不到指標事件。
  3. 本組件為純 UGUI 事件驅動不依賴 Unity New InputSystem 的 OnScreen 控制項,Old / New Input 後端皆可搭配使用。

輸出流程

  1. 按下 (OnPointerDown):非 Fixed 類型會將搖桿背景重新定位至按壓點,記錄按壓起始位置並立即執行一次 OnDrag
  2. 拖曳 (OnDrag):以「當前位置 - 按壓起始位置」換算輸出向量 (除以 handleMovementRange * Canvas.scaleFactor),依序套用軸向限制死區過濾向量模式,最後透過 onStickInput 輸出並更新把手位置。
  3. 放開 (OnPointerUp):把手歸位 (中心),onStickInput 回傳 Vector2.zero

列舉

StickVectorMode

public enum StickVectorMode
{
Normalized,
Delta
}

搖桿向量輸出模式:

說明
Normalized輸出範圍限制在 -1.00 ~ 1.00 (向量長度超過 1 會進行正規化),適合移動控制。
Delta模仿 Mouse Delta,輸出可大於 1,適合視角控制 (可自行乘上靈敏度)。

StickType

public enum StickType
{
Fixed = 0,
Floating = 1
}

搖桿顯示類型:

說明
Fixed搖桿固定於原位置。
Floating每次按下時,搖桿背景會重新定位至按壓點。

AxisConstraint

public enum AxisConstraint
{
Both = 0,
Horizontal = 1,
Vertical = 2
}

限制搖桿輸出方向:

說明
Both雙軸輸出。
Horizontal僅輸出水平軸。
Vertical僅輸出垂直軸。

成員

成員總覽

成員說明
onStickInput搖桿輸出向量變化時的回調 (放開時回傳 Vector2.zero)。
stickVectorMode搖桿向量輸出模式 (StickVectorMode)。
stickType搖桿顯示類型 (StickType)。
axisConstraint限制搖桿輸出方向 (AxisConstraint)。
handleMovementRange搖桿把手控制範圍 (像素半徑,預設 100)。
deadZone死區範圍 (0 ~ 1),低於此值的搖桿輸入視為無效。

onStickInput

public Action<Vector2> onStickInput

當搖桿輸出向量變化時的回調:拖曳期間每次輸入變化皆會觸發,放開時會回傳 Vector2.zero

this._joystick.onStickInput += (v2) => this._move = v2;

重要 onStickInputAction<Vector2> 委派欄位,使用 = 直接指定會覆蓋所有既有訂閱,建議使用 += / -= 進行訂閱與取消訂閱 (並於物件銷毀時取消訂閱)。

stickVectorMode

public StickVectorMode stickVectorMode { get; set; }

搖桿向量輸出模式,預設 StickVectorMode.Normalized (詳見 StickVectorMode)。

stickType

public StickType stickType { get; set; }

搖桿顯示類型,預設 StickType.Fixed (詳見 StickType)。

axisConstraint

public AxisConstraint axisConstraint { get; set; }

限制搖桿輸出方向,預設 AxisConstraint.Both (詳見 AxisConstraint)。

handleMovementRange

public float handleMovementRange { get; set; }

搖桿把手控制範圍 (像素半徑,預設 100),輸出向量以「拖曳位移 / (handleMovementRange * Canvas.scaleFactor)」進行換算。

注意 控制範圍以像素為單位並受 Canvas scaleFactor 影響,建議於目標解析度 / 縱橫比進行測試。

deadZone

public float deadZone { get; set; }

死區範圍 (0 ~ 1,預設 0),輸出向量長度低於此值將視為無效並輸出 Vector2.zero (避免誤觸)。

提醒 死區為控制範圍的比例值,約 0.05 ~ 0.15 即可過濾誤觸且不影響操作靈敏度。


Inspector 欄位

以下序列化欄位僅能於 Inspector 配置 (無公開屬性);可透過 Package Manager -> Samples 匯入 VirtualJoystickUI Prefab (已預先串接,詳見模塊介紹):

欄位 (Inspector)說明
Background (_background)搖桿背景 UI 元件 (RectTransform,搖桿底圖),必須指定
Handle (_handle)搖桿把手 UI 元件 (RectTransform,可拖曳的控制點),必須指定
Show Only When Pressed (_showOnlyWhenPressed)是否僅在按下時顯示搖桿背景 (Awake 即隱藏,按下顯示、放開隱藏),適合搭配 Floating 類型。

UGUI 事件回調

方法總覽

方法說明
OnPointerDown按下時觸發 (重新定位與初始輸出)。
OnPointerUp放開時觸發 (把手歸位並輸出歸零)。
OnDrag拖曳時觸發 (計算並輸出搖桿向量)。

注意 以上方法為 UGUI 事件介面實作 (IPointerDownHandlerIPointerUpHandlerIDragHandler),由 EventSystem 自動驅動,一般情況下無需手動呼叫


OnPointerDown

public void OnPointerDown(PointerEventData eventData)

按下時觸發:顯示搖桿背景 (若為隱藏狀態),非 Fixed 類型會將搖桿背景重新定位至按壓點,記錄按壓起始位置並立即執行一次 OnDrag

OnPointerUp

public void OnPointerUp(PointerEventData eventData)

放開時觸發:把手歸位 (中心點),若啟用 Show Only When Pressed 會隱藏搖桿背景,並透過 onStickInput 回傳 Vector2.zero

OnDrag

public void OnDrag(PointerEventData eventData)

拖曳時觸發:依按壓起始位置計算輸出向量,依序套用軸向限制死區過濾向量模式,透過 onStickInput 輸出,並同步更新把手位置 (視覺上以 handleMovementRange 為上限)。