VirtualJoystick
Coding Style wiki
VirtualJoystick 是 UGUI 虛擬搖桿組件 (MonoBehaviour),實作 UGUI 事件介面 (IPointerDownHandler、IPointerUpHandler、IDragHandler),將觸控 / 滑鼠拖曳轉換為 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;
}
}
通用規則
環境需求
- 組件必須位於 Canvas 之下:
Awake會取得父層 Canvas (用於解析比例與位置換算),找不到會報錯並自我停用 (enabled = false)。 - 場景中需有 EventSystem,且組件上的
Image需可接收 Raycast (未被CanvasGroup.blocksRaycasts = false等阻擋),否則收不到指標事件。 - 本組件為純 UGUI 事件驅動,不依賴 Unity New InputSystem 的 OnScreen 控制項,Old / New Input 後端皆可搭配使用。
輸出流程
- 按下 (OnPointerDown):非
Fixed類型會將搖桿背景重新定位至按壓點,記錄按壓起始位置並立即執行一次OnDrag。 - 拖曳 (OnDrag):以「當前位置 - 按壓起始位置」換算輸出向量 (除以
handleMovementRange * Canvas.scaleFactor),依序套用軸向限制、死區過濾與向量模式,最後透過onStickInput輸出並更新把手位置。 - 放開 (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;
重要 onStickInput 為 Action<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 事件介面實作 (IPointerDownHandler、IPointerUpHandler、IDragHandler),由 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 為上限)。